LCOV - code coverage report
Current view: top level - widget - nsNativeTheme.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 64 362 17.7 %
Date: 2017-07-14 16:53:18 Functions: 11 37 29.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsNativeTheme.h"
       7             : #include "nsIWidget.h"
       8             : #include "nsIDocument.h"
       9             : #include "nsIContent.h"
      10             : #include "nsIFrame.h"
      11             : #include "nsIPresShell.h"
      12             : #include "nsNumberControlFrame.h"
      13             : #include "nsPresContext.h"
      14             : #include "nsString.h"
      15             : #include "nsNameSpaceManager.h"
      16             : #include "nsIDOMHTMLInputElement.h"
      17             : #include "nsIDOMXULMenuListElement.h"
      18             : #include "nsThemeConstants.h"
      19             : #include "nsIComponentManager.h"
      20             : #include "nsPIDOMWindow.h"
      21             : #include "nsProgressFrame.h"
      22             : #include "nsMeterFrame.h"
      23             : #include "nsMenuFrame.h"
      24             : #include "nsRangeFrame.h"
      25             : #include "nsCSSRendering.h"
      26             : #include "mozilla/EventStates.h"
      27             : #include "mozilla/dom/Element.h"
      28             : #include "mozilla/dom/HTMLBodyElement.h"
      29             : #include "mozilla/dom/HTMLProgressElement.h"
      30             : #include "nsIDocumentInlines.h"
      31             : #include <algorithm>
      32             : 
      33             : using namespace mozilla;
      34             : using namespace mozilla::dom;
      35             : 
      36           2 : nsNativeTheme::nsNativeTheme()
      37           2 : : mAnimatedContentTimeout(UINT32_MAX)
      38             : {
      39           2 : }
      40             : 
      41          16 : NS_IMPL_ISUPPORTS(nsNativeTheme, nsITimerCallback)
      42             : 
      43             : nsIPresShell *
      44          18 : nsNativeTheme::GetPresShell(nsIFrame* aFrame)
      45             : {
      46          18 :   if (!aFrame)
      47           0 :     return nullptr;
      48             : 
      49          18 :   nsPresContext* context = aFrame->PresContext();
      50          18 :   return context ? context->GetPresShell() : nullptr;
      51             : }
      52             : 
      53             : EventStates
      54          18 : nsNativeTheme::GetContentState(nsIFrame* aFrame, uint8_t aWidgetType)
      55             : {
      56          18 :   if (!aFrame)
      57           0 :     return EventStates();
      58             : 
      59             :   bool isXULCheckboxRadio = 
      60          18 :     (aWidgetType == NS_THEME_CHECKBOX ||
      61          18 :      aWidgetType == NS_THEME_RADIO) &&
      62          18 :     aFrame->GetContent()->IsXULElement();
      63          18 :   if (isXULCheckboxRadio)
      64           0 :     aFrame = aFrame->GetParent();
      65             : 
      66          18 :   if (!aFrame->GetContent())
      67           0 :     return EventStates();
      68             : 
      69          18 :   nsIPresShell *shell = GetPresShell(aFrame);
      70          18 :   if (!shell)
      71           0 :     return EventStates();
      72             : 
      73          18 :   nsIContent* frameContent = aFrame->GetContent();
      74          18 :   EventStates flags;
      75          18 :   if (frameContent->IsElement()) {
      76          18 :     flags = frameContent->AsElement()->State();
      77             : 
      78             :     // <input type=number> needs special handling since its nested native
      79             :     // anonymous <input type=text> takes focus for it.
      80          18 :     if (aWidgetType == NS_THEME_NUMBER_INPUT &&
      81           0 :         frameContent->IsHTMLElement(nsGkAtoms::input)) {
      82           0 :       nsNumberControlFrame *numberControlFrame = do_QueryFrame(aFrame);
      83           0 :       if (numberControlFrame && numberControlFrame->IsFocused()) {
      84           0 :         flags |= NS_EVENT_STATE_FOCUS;
      85             :       }
      86             :     }
      87             : 
      88             :     nsNumberControlFrame* numberControlFrame =
      89          18 :       nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame);
      90          54 :     if (numberControlFrame &&
      91          18 :         numberControlFrame->GetContent()->AsElement()->State().
      92          18 :           HasState(NS_EVENT_STATE_DISABLED)) {
      93           0 :       flags |= NS_EVENT_STATE_DISABLED;
      94             :     }
      95             :   }
      96             :   
      97          18 :   if (isXULCheckboxRadio && aWidgetType == NS_THEME_RADIO) {
      98           0 :     if (IsFocused(aFrame))
      99           0 :       flags |= NS_EVENT_STATE_FOCUS;
     100             :   }
     101             : 
     102             :   // On Windows and Mac, only draw focus rings if they should be shown. This
     103             :   // means that focus rings are only shown once the keyboard has been used to
     104             :   // focus something in the window.
     105             : #if defined(XP_MACOSX)
     106             :   // Mac always draws focus rings for textboxes and lists.
     107             :   if (aWidgetType == NS_THEME_NUMBER_INPUT ||
     108             :       aWidgetType == NS_THEME_TEXTFIELD ||
     109             :       aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
     110             :       aWidgetType == NS_THEME_SEARCHFIELD ||
     111             :       aWidgetType == NS_THEME_LISTBOX) {
     112             :     return flags;
     113             :   }
     114             : #endif
     115             : #if defined(XP_WIN)
     116             :   // On Windows, focused buttons are always drawn as such by the native theme.
     117             :   if (aWidgetType == NS_THEME_BUTTON)
     118             :     return flags;
     119             : #endif    
     120             : #if defined(XP_MACOSX) || defined(XP_WIN)
     121             :   nsIDocument* doc = aFrame->GetContent()->OwnerDoc();
     122             :   nsPIDOMWindowOuter* window = doc->GetWindow();
     123             :   if (window && !window->ShouldShowFocusRing())
     124             :     flags &= ~NS_EVENT_STATE_FOCUS;
     125             : #endif
     126             :   
     127          18 :   return flags;
     128             : }
     129             : 
     130             : /* static */
     131             : bool
     132          36 : nsNativeTheme::CheckBooleanAttr(nsIFrame* aFrame, nsIAtom* aAtom)
     133             : {
     134          36 :   if (!aFrame)
     135           0 :     return false;
     136             : 
     137          36 :   nsIContent* content = aFrame->GetContent();
     138          36 :   if (!content)
     139           0 :     return false;
     140             : 
     141          36 :   if (content->IsHTMLElement())
     142           0 :     return content->HasAttr(kNameSpaceID_None, aAtom);
     143             : 
     144             :   // For XML/XUL elements, an attribute must be equal to the literal
     145             :   // string "true" to be counted as true.  An empty string should _not_
     146             :   // be counted as true.
     147          36 :   return content->AttrValueIs(kNameSpaceID_None, aAtom,
     148          72 :                               NS_LITERAL_STRING("true"), eCaseMatters);
     149             : }
     150             : 
     151             : /* static */
     152             : int32_t
     153           0 : nsNativeTheme::CheckIntAttr(nsIFrame* aFrame, nsIAtom* aAtom, int32_t defaultValue)
     154             : {
     155           0 :   if (!aFrame)
     156           0 :     return defaultValue;
     157             : 
     158           0 :   nsAutoString attr;
     159           0 :   aFrame->GetContent()->GetAttr(kNameSpaceID_None, aAtom, attr);
     160             :   nsresult err;
     161           0 :   int32_t value = attr.ToInteger(&err);
     162           0 :   if (attr.IsEmpty() || NS_FAILED(err))
     163           0 :     return defaultValue;
     164             : 
     165           0 :   return value;
     166             : }
     167             : 
     168             : /* static */
     169             : double
     170           0 : nsNativeTheme::GetProgressValue(nsIFrame* aFrame)
     171             : {
     172             :   // When we are using the HTML progress element,
     173             :   // we can get the value from the IDL property.
     174           0 :   if (aFrame && aFrame->GetContent()->IsHTMLElement(nsGkAtoms::progress)) {
     175           0 :     return static_cast<HTMLProgressElement*>(aFrame->GetContent())->Value();
     176             :   }
     177             : 
     178           0 :   return (double)nsNativeTheme::CheckIntAttr(aFrame, nsGkAtoms::value, 0);
     179             : }
     180             : 
     181             : /* static */
     182             : double
     183           0 : nsNativeTheme::GetProgressMaxValue(nsIFrame* aFrame)
     184             : {
     185             :   // When we are using the HTML progress element,
     186             :   // we can get the max from the IDL property.
     187           0 :   if (aFrame && aFrame->GetContent()->IsHTMLElement(nsGkAtoms::progress)) {
     188           0 :     return static_cast<HTMLProgressElement*>(aFrame->GetContent())->Max();
     189             :   }
     190             : 
     191           0 :   return (double)std::max(nsNativeTheme::CheckIntAttr(aFrame, nsGkAtoms::max, 100), 1);
     192             : }
     193             : 
     194             : bool
     195           0 : nsNativeTheme::GetCheckedOrSelected(nsIFrame* aFrame, bool aCheckSelected)
     196             : {
     197           0 :   if (!aFrame)
     198           0 :     return false;
     199             : 
     200           0 :   nsIContent* content = aFrame->GetContent();
     201             : 
     202           0 :   if (content->IsXULElement()) {
     203             :     // For a XUL checkbox or radio button, the state of the parent determines
     204             :     // the checked state
     205           0 :     aFrame = aFrame->GetParent();
     206             :   } else {
     207             :     // Check for an HTML input element
     208           0 :     nsCOMPtr<nsIDOMHTMLInputElement> inputElt = do_QueryInterface(content);
     209           0 :     if (inputElt) {
     210             :       bool checked;
     211           0 :       inputElt->GetChecked(&checked);
     212           0 :       return checked;
     213             :     }
     214             :   }
     215             : 
     216           0 :   return CheckBooleanAttr(aFrame, aCheckSelected ? nsGkAtoms::selected
     217           0 :                                                  : nsGkAtoms::checked);
     218             : }
     219             : 
     220             : bool
     221           0 : nsNativeTheme::IsButtonTypeMenu(nsIFrame* aFrame)
     222             : {
     223           0 :   if (!aFrame)
     224           0 :     return false;
     225             : 
     226           0 :   nsIContent* content = aFrame->GetContent();
     227           0 :   return content->IsXULElement(nsGkAtoms::button) &&
     228           0 :          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
     229           0 :                               NS_LITERAL_STRING("menu"), eCaseMatters);
     230             : }
     231             : 
     232             : bool
     233           0 : nsNativeTheme::IsPressedButton(nsIFrame* aFrame)
     234             : {
     235           0 :   EventStates eventState = GetContentState(aFrame, NS_THEME_TOOLBARBUTTON);
     236           0 :   if (IsDisabled(aFrame, eventState))
     237           0 :     return false;
     238             : 
     239           0 :   return IsOpenButton(aFrame) ||
     240           0 :          eventState.HasAllStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_HOVER);
     241             : }
     242             : 
     243             : 
     244             : bool
     245           0 : nsNativeTheme::GetIndeterminate(nsIFrame* aFrame)
     246             : {
     247           0 :   if (!aFrame)
     248           0 :     return false;
     249             : 
     250           0 :   nsIContent* content = aFrame->GetContent();
     251             : 
     252           0 :   if (content->IsXULElement()) {
     253             :     // For a XUL checkbox or radio button, the state of the parent determines
     254             :     // the state
     255           0 :     return CheckBooleanAttr(aFrame->GetParent(), nsGkAtoms::indeterminate);
     256             :   }
     257             : 
     258             :   // Check for an HTML input element
     259           0 :   nsCOMPtr<nsIDOMHTMLInputElement> inputElt = do_QueryInterface(content);
     260           0 :   if (inputElt) {
     261             :     bool indeterminate;
     262           0 :     inputElt->GetIndeterminate(&indeterminate);
     263           0 :     return indeterminate;
     264             :   }
     265             : 
     266           0 :   return false;
     267             : }
     268             : 
     269             : bool
     270        1268 : nsNativeTheme::IsWidgetStyled(nsPresContext* aPresContext, nsIFrame* aFrame,
     271             :                               uint8_t aWidgetType)
     272             : {
     273             :   // Check for specific widgets to see if HTML has overridden the style.
     274        1268 :   if (!aFrame)
     275           0 :     return false;
     276             : 
     277             :   // Resizers have some special handling, dependent on whether in a scrollable
     278             :   // container or not. If so, use the scrollable container's to determine
     279             :   // whether the style is overriden instead of the resizer. This allows a
     280             :   // non-native transparent resizer to be used instead. Otherwise, we just
     281             :   // fall through and return false.
     282        1268 :   if (aWidgetType == NS_THEME_RESIZER) {
     283           0 :     nsIFrame* parentFrame = aFrame->GetParent();
     284           0 :     if (parentFrame && parentFrame->IsScrollFrame()) {
     285             :       // if the parent is a scrollframe, the resizer should be native themed
     286             :       // only if the scrollable area doesn't override the widget style.
     287           0 :       parentFrame = parentFrame->GetParent();
     288           0 :       if (parentFrame) {
     289           0 :         return IsWidgetStyled(aPresContext, parentFrame,
     290           0 :                               parentFrame->StyleDisplay()->mAppearance);
     291             :       }
     292             :     }
     293             :   }
     294             : 
     295             :   /**
     296             :    * Progress bar appearance should be the same for the bar and the container
     297             :    * frame. nsProgressFrame owns the logic and will tell us what we should do.
     298             :    */
     299        1268 :   if (aWidgetType == NS_THEME_PROGRESSCHUNK ||
     300             :       aWidgetType == NS_THEME_PROGRESSBAR) {
     301           0 :     nsProgressFrame* progressFrame = do_QueryFrame(aWidgetType == NS_THEME_PROGRESSCHUNK
     302           0 :                                        ? aFrame->GetParent() : aFrame);
     303           0 :     if (progressFrame) {
     304           0 :       return !progressFrame->ShouldUseNativeStyle();
     305             :     }
     306             :   }
     307             : 
     308             :   /**
     309             :    * Meter bar appearance should be the same for the bar and the container
     310             :    * frame. nsMeterFrame owns the logic and will tell us what we should do.
     311             :    */
     312        1268 :   if (aWidgetType == NS_THEME_METERCHUNK ||
     313             :       aWidgetType == NS_THEME_METERBAR) {
     314           0 :     nsMeterFrame* meterFrame = do_QueryFrame(aWidgetType == NS_THEME_METERCHUNK
     315           0 :                                        ? aFrame->GetParent() : aFrame);
     316           0 :     if (meterFrame) {
     317           0 :       return !meterFrame->ShouldUseNativeStyle();
     318             :     }
     319             :   }
     320             : 
     321             :   /**
     322             :    * An nsRangeFrame and its children are treated atomically when it
     323             :    * comes to native theming (either all parts, or no parts, are themed).
     324             :    * nsRangeFrame owns the logic and will tell us what we should do.
     325             :    */
     326        1268 :   if (aWidgetType == NS_THEME_RANGE ||
     327             :       aWidgetType == NS_THEME_RANGE_THUMB) {
     328             :     nsRangeFrame* rangeFrame =
     329           0 :       do_QueryFrame(aWidgetType == NS_THEME_RANGE_THUMB
     330           0 :                       ? aFrame->GetParent() : aFrame);
     331           0 :     if (rangeFrame) {
     332           0 :       return !rangeFrame->ShouldUseNativeStyle();
     333             :     }
     334             :   }
     335             : 
     336        1268 :   if (aWidgetType == NS_THEME_SPINNER_UPBUTTON ||
     337             :       aWidgetType == NS_THEME_SPINNER_DOWNBUTTON) {
     338             :     nsNumberControlFrame* numberControlFrame =
     339           0 :       nsNumberControlFrame::GetNumberControlFrameForSpinButton(aFrame);
     340           0 :     if (numberControlFrame) {
     341           0 :       return !numberControlFrame->ShouldUseNativeStyleForSpinner();
     342             :     }
     343             :   }
     344             : 
     345        1268 :   return (aWidgetType == NS_THEME_NUMBER_INPUT ||
     346        1268 :           aWidgetType == NS_THEME_BUTTON ||
     347        1268 :           aWidgetType == NS_THEME_TEXTFIELD ||
     348        1268 :           aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
     349        1268 :           aWidgetType == NS_THEME_LISTBOX ||
     350           0 :           aWidgetType == NS_THEME_MENULIST) &&
     351        1268 :          aFrame->GetContent()->IsHTMLElement() &&
     352           0 :          aPresContext->HasAuthorSpecifiedRules(aFrame,
     353             :                                                NS_AUTHOR_SPECIFIED_BORDER |
     354        1268 :                                                NS_AUTHOR_SPECIFIED_BACKGROUND);
     355             : }
     356             : 
     357             : bool
     358          18 : nsNativeTheme::IsDisabled(nsIFrame* aFrame, EventStates aEventStates)
     359             : {
     360          18 :   if (!aFrame) {
     361           0 :     return false;
     362             :   }
     363             : 
     364          18 :   nsIContent* content = aFrame->GetContent();
     365          18 :   if (!content) {
     366           0 :     return false;
     367             :   }
     368             : 
     369          18 :   if (content->IsHTMLElement()) {
     370           0 :     return aEventStates.HasState(NS_EVENT_STATE_DISABLED);
     371             :   }
     372             : 
     373             :   // For XML/XUL elements, an attribute must be equal to the literal
     374             :   // string "true" to be counted as true.  An empty string should _not_
     375             :   // be counted as true.
     376          18 :   return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
     377          36 :                               NS_LITERAL_STRING("true"), eCaseMatters);
     378             : }
     379             : 
     380             : /* static */ bool
     381         404 : nsNativeTheme::IsFrameRTL(nsIFrame* aFrame)
     382             : {
     383         404 :   if (!aFrame) {
     384           0 :     return false;
     385             :   }
     386         404 :   WritingMode wm = aFrame->GetWritingMode();
     387         404 :   return !(wm.IsVertical() ? wm.IsVerticalLR() : wm.IsBidiLTR());
     388             : }
     389             : 
     390             : bool
     391           0 : nsNativeTheme::IsHTMLContent(nsIFrame *aFrame)
     392             : {
     393           0 :   if (!aFrame) {
     394           0 :     return false;
     395             :   }
     396           0 :   nsIContent* content = aFrame->GetContent();
     397           0 :   return content && content->IsHTMLElement();
     398             : }
     399             : 
     400             : 
     401             : // scrollbar button:
     402             : int32_t
     403           0 : nsNativeTheme::GetScrollbarButtonType(nsIFrame* aFrame)
     404             : {
     405           0 :   if (!aFrame)
     406           0 :     return 0;
     407             : 
     408             :   static nsIContent::AttrValuesArray strings[] =
     409             :     {&nsGkAtoms::scrollbarDownBottom, &nsGkAtoms::scrollbarDownTop,
     410             :      &nsGkAtoms::scrollbarUpBottom, &nsGkAtoms::scrollbarUpTop,
     411             :      nullptr};
     412             : 
     413           0 :   switch (aFrame->GetContent()->FindAttrValueIn(kNameSpaceID_None,
     414             :                                                 nsGkAtoms::sbattr,
     415           0 :                                                 strings, eCaseMatters)) {
     416           0 :     case 0: return eScrollbarButton_Down | eScrollbarButton_Bottom;
     417           0 :     case 1: return eScrollbarButton_Down;
     418           0 :     case 2: return eScrollbarButton_Bottom;
     419           0 :     case 3: return eScrollbarButton_UpTop;
     420             :   }
     421             : 
     422           0 :   return 0;
     423             : }
     424             : 
     425             : // treeheadercell:
     426             : nsNativeTheme::TreeSortDirection
     427           0 : nsNativeTheme::GetTreeSortDirection(nsIFrame* aFrame)
     428             : {
     429           0 :   if (!aFrame || !aFrame->GetContent())
     430           0 :     return eTreeSortDirection_Natural;
     431             : 
     432             :   static nsIContent::AttrValuesArray strings[] =
     433             :     {&nsGkAtoms::descending, &nsGkAtoms::ascending, nullptr};
     434           0 :   switch (aFrame->GetContent()->FindAttrValueIn(kNameSpaceID_None,
     435             :                                                 nsGkAtoms::sortDirection,
     436           0 :                                                 strings, eCaseMatters)) {
     437           0 :     case 0: return eTreeSortDirection_Descending;
     438           0 :     case 1: return eTreeSortDirection_Ascending;
     439             :   }
     440             : 
     441           0 :   return eTreeSortDirection_Natural;
     442             : }
     443             : 
     444             : bool
     445           0 : nsNativeTheme::IsLastTreeHeaderCell(nsIFrame* aFrame)
     446             : {
     447           0 :   if (!aFrame)
     448           0 :     return false;
     449             : 
     450             :   // A tree column picker is always the last header cell.
     451           0 :   if (aFrame->GetContent()->IsXULElement(nsGkAtoms::treecolpicker))
     452           0 :     return true;
     453             : 
     454             :   // Find the parent tree.
     455           0 :   nsIContent* parent = aFrame->GetContent()->GetParent();
     456           0 :   while (parent && !parent->IsXULElement(nsGkAtoms::tree)) {
     457           0 :     parent = parent->GetParent();
     458             :   }
     459             : 
     460             :   // If the column picker is visible, this can't be the last column.
     461           0 :   if (parent && !parent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidecolumnpicker,
     462           0 :                                      NS_LITERAL_STRING("true"), eCaseMatters))
     463           0 :     return false;
     464             : 
     465           0 :   while ((aFrame = aFrame->GetNextSibling())) {
     466           0 :     if (aFrame->GetRect().width > 0)
     467           0 :       return false;
     468             :   }
     469           0 :   return true;
     470             : }
     471             : 
     472             : // tab:
     473             : bool
     474           0 : nsNativeTheme::IsBottomTab(nsIFrame* aFrame)
     475             : {
     476           0 :   if (!aFrame)
     477           0 :     return false;
     478             : 
     479           0 :   nsAutoString classStr;
     480           0 :   aFrame->GetContent()->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, classStr);
     481           0 :   return !classStr.IsEmpty() && classStr.Find("tab-bottom") != kNotFound;
     482             : }
     483             : 
     484             : bool
     485           0 : nsNativeTheme::IsFirstTab(nsIFrame* aFrame)
     486             : {
     487           0 :   if (!aFrame)
     488           0 :     return false;
     489             : 
     490           0 :   for (nsIFrame* first : aFrame->GetParent()->PrincipalChildList()) {
     491           0 :     if (first->GetRect().width > 0 &&
     492           0 :         first->GetContent()->IsXULElement(nsGkAtoms::tab))
     493           0 :       return (first == aFrame);
     494             :   }
     495           0 :   return false;
     496             : }
     497             : 
     498             : bool
     499           0 : nsNativeTheme::IsHorizontal(nsIFrame* aFrame)
     500             : {
     501           0 :   if (!aFrame)
     502           0 :     return false;
     503             :     
     504           0 :   return !aFrame->GetContent()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::orient,
     505             :                                             nsGkAtoms::vertical, 
     506           0 :                                             eCaseMatters);
     507             : }
     508             : 
     509             : bool
     510           0 : nsNativeTheme::IsNextToSelectedTab(nsIFrame* aFrame, int32_t aOffset)
     511             : {
     512           0 :   if (!aFrame)
     513           0 :     return false;
     514             : 
     515           0 :   if (aOffset == 0)
     516           0 :     return IsSelectedTab(aFrame);
     517             : 
     518           0 :   int32_t thisTabIndex = -1, selectedTabIndex = -1;
     519             : 
     520           0 :   nsIFrame* currentTab = aFrame->GetParent()->PrincipalChildList().FirstChild();
     521           0 :   for (int32_t i = 0; currentTab; currentTab = currentTab->GetNextSibling()) {
     522           0 :     if (currentTab->GetRect().width == 0)
     523           0 :       continue;
     524           0 :     if (aFrame == currentTab)
     525           0 :       thisTabIndex = i;
     526           0 :     if (IsSelectedTab(currentTab))
     527           0 :       selectedTabIndex = i;
     528           0 :     ++i;
     529             :   }
     530             : 
     531           0 :   if (thisTabIndex == -1 || selectedTabIndex == -1)
     532           0 :     return false;
     533             : 
     534           0 :   return (thisTabIndex - selectedTabIndex == aOffset);
     535             : }
     536             : 
     537             : // progressbar:
     538             : bool
     539           0 : nsNativeTheme::IsIndeterminateProgress(nsIFrame* aFrame,
     540             :                                        EventStates aEventStates)
     541             : {
     542           0 :   if (!aFrame || !aFrame->GetContent())
     543           0 :     return false;
     544             : 
     545           0 :   if (aFrame->GetContent()->IsHTMLElement(nsGkAtoms::progress)) {
     546           0 :     return aEventStates.HasState(NS_EVENT_STATE_INDETERMINATE);
     547             :   }
     548             : 
     549           0 :   return aFrame->GetContent()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mode,
     550           0 :                                            NS_LITERAL_STRING("undetermined"),
     551           0 :                                            eCaseMatters);
     552             : }
     553             : 
     554             : bool
     555           0 : nsNativeTheme::IsVerticalProgress(nsIFrame* aFrame)
     556             : {
     557           0 :   if (!aFrame) {
     558           0 :     return false;
     559             :   }
     560           0 :   return IsVerticalMeter(aFrame);
     561             : }
     562             : 
     563             : bool
     564           0 : nsNativeTheme::IsVerticalMeter(nsIFrame* aFrame)
     565             : {
     566           0 :   NS_PRECONDITION(aFrame, "You have to pass a non-null aFrame");
     567           0 :   switch (aFrame->StyleDisplay()->mOrient) {
     568             :     case StyleOrient::Horizontal:
     569           0 :       return false;
     570             :     case StyleOrient::Vertical:
     571           0 :       return true;
     572             :     case StyleOrient::Inline:
     573           0 :       return aFrame->GetWritingMode().IsVertical();
     574             :     case StyleOrient::Block:
     575           0 :       return !aFrame->GetWritingMode().IsVertical();
     576             :   }
     577           0 :   NS_NOTREACHED("unexpected -moz-orient value");
     578           0 :   return false;
     579             : }
     580             : 
     581             : // menupopup:
     582             : bool
     583           0 : nsNativeTheme::IsSubmenu(nsIFrame* aFrame, bool* aLeftOfParent)
     584             : {
     585           0 :   if (!aFrame)
     586           0 :     return false;
     587             : 
     588           0 :   nsIContent* parentContent = aFrame->GetContent()->GetParent();
     589           0 :   if (!parentContent || !parentContent->IsXULElement(nsGkAtoms::menu))
     590           0 :     return false;
     591             : 
     592           0 :   nsIFrame* parent = aFrame;
     593           0 :   while ((parent = parent->GetParent())) {
     594           0 :     if (parent->GetContent() == parentContent) {
     595           0 :       if (aLeftOfParent) {
     596           0 :         LayoutDeviceIntRect selfBounds, parentBounds;
     597           0 :         selfBounds = aFrame->GetNearestWidget()->GetScreenBounds();
     598           0 :         parentBounds = parent->GetNearestWidget()->GetScreenBounds();
     599           0 :         *aLeftOfParent = selfBounds.x < parentBounds.x;
     600             :       }
     601           0 :       return true;
     602             :     }
     603             :   }
     604             : 
     605           0 :   return false;
     606             : }
     607             : 
     608             : bool
     609         154 : nsNativeTheme::IsRegularMenuItem(nsIFrame *aFrame)
     610             : {
     611         154 :   nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
     612         154 :   return !(menuFrame && (menuFrame->IsOnMenuBar() ||
     613         154 :                          menuFrame->GetParentMenuListType() != eNotMenuList));
     614             : }
     615             : 
     616             : bool
     617           0 : nsNativeTheme::IsMenuListEditable(nsIFrame *aFrame)
     618             : {
     619           0 :   bool isEditable = false;
     620           0 :   nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(aFrame->GetContent());
     621           0 :   if (menulist)
     622           0 :     menulist->GetEditable(&isEditable);
     623           0 :   return isEditable;
     624             : }
     625             : 
     626             : bool
     627           0 : nsNativeTheme::QueueAnimatedContentForRefresh(nsIContent* aContent,
     628             :                                               uint32_t aMinimumFrameRate)
     629             : {
     630           0 :   NS_ASSERTION(aContent, "Null pointer!");
     631           0 :   NS_ASSERTION(aMinimumFrameRate, "aMinimumFrameRate must be non-zero!");
     632           0 :   NS_ASSERTION(aMinimumFrameRate <= 1000,
     633             :                "aMinimumFrameRate must be less than 1000!");
     634             : 
     635           0 :   uint32_t timeout = 1000 / aMinimumFrameRate;
     636           0 :   timeout = std::min(mAnimatedContentTimeout, timeout);
     637             : 
     638           0 :   if (!mAnimatedContentTimer) {
     639           0 :     mAnimatedContentTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     640           0 :     NS_ENSURE_TRUE(mAnimatedContentTimer, false);
     641             :   }
     642             : 
     643           0 :   if (mAnimatedContentList.IsEmpty() || timeout != mAnimatedContentTimeout) {
     644             :     nsresult rv;
     645           0 :     if (!mAnimatedContentList.IsEmpty()) {
     646           0 :       rv = mAnimatedContentTimer->Cancel();
     647           0 :       NS_ENSURE_SUCCESS(rv, false);
     648             :     }
     649             : 
     650           0 :     if (XRE_IsContentProcess() && NS_IsMainThread()) {
     651           0 :       mAnimatedContentTimer->SetTarget(aContent->OwnerDoc()->EventTargetFor(TaskCategory::Other));
     652             :     }
     653           0 :     rv = mAnimatedContentTimer->InitWithCallback(this, timeout,
     654           0 :                                                  nsITimer::TYPE_ONE_SHOT);
     655           0 :     NS_ENSURE_SUCCESS(rv, false);
     656             : 
     657           0 :     mAnimatedContentTimeout = timeout;
     658             :   }
     659             : 
     660           0 :   if (!mAnimatedContentList.AppendElement(aContent)) {
     661           0 :     NS_WARNING("Out of memory!");
     662           0 :     return false;
     663             :   }
     664             : 
     665           0 :   return true;
     666             : }
     667             : 
     668             : NS_IMETHODIMP
     669           0 : nsNativeTheme::Notify(nsITimer* aTimer)
     670             : {
     671           0 :   NS_ASSERTION(aTimer == mAnimatedContentTimer, "Wrong timer!");
     672             : 
     673             :   // XXX Assumes that calling nsIFrame::Invalidate won't reenter
     674             :   //     QueueAnimatedContentForRefresh.
     675             : 
     676           0 :   uint32_t count = mAnimatedContentList.Length();
     677           0 :   for (uint32_t index = 0; index < count; index++) {
     678           0 :     nsIFrame* frame = mAnimatedContentList[index]->GetPrimaryFrame();
     679           0 :     if (frame) {
     680           0 :       frame->InvalidateFrame();
     681             :     }
     682             :   }
     683             : 
     684           0 :   mAnimatedContentList.Clear();
     685           0 :   mAnimatedContentTimeout = UINT32_MAX;
     686           0 :   return NS_OK;
     687             : }
     688             : 
     689             : nsIFrame*
     690           0 : nsNativeTheme::GetAdjacentSiblingFrameWithSameAppearance(nsIFrame* aFrame,
     691             :                                                          bool aNextSibling)
     692             : {
     693           0 :   if (!aFrame)
     694           0 :     return nullptr;
     695             : 
     696             :   // Find the next visible sibling.
     697           0 :   nsIFrame* sibling = aFrame;
     698           0 :   do {
     699           0 :     sibling = aNextSibling ? sibling->GetNextSibling() : sibling->GetPrevSibling();
     700           0 :   } while (sibling && sibling->GetRect().width == 0);
     701             : 
     702             :   // Check same appearance and adjacency.
     703           0 :   if (!sibling ||
     704           0 :       sibling->StyleDisplay()->mAppearance != aFrame->StyleDisplay()->mAppearance ||
     705           0 :       (sibling->GetRect().XMost() != aFrame->GetRect().x &&
     706           0 :        aFrame->GetRect().XMost() != sibling->GetRect().x))
     707           0 :     return nullptr;
     708           0 :   return sibling;
     709             : }
     710             : 
     711             : bool
     712           0 : nsNativeTheme::IsRangeHorizontal(nsIFrame* aFrame)
     713             : {
     714           0 :   nsIFrame* rangeFrame = aFrame;
     715           0 :   if (!rangeFrame->IsRangeFrame()) {
     716             :     // If the thumb's frame is passed in, get its range parent:
     717           0 :     rangeFrame = aFrame->GetParent();
     718             :   }
     719           0 :   if (rangeFrame->IsRangeFrame()) {
     720           0 :     return static_cast<nsRangeFrame*>(rangeFrame)->IsHorizontal();
     721             :   }
     722             :   // Not actually a range frame - just use the ratio of the frame's size to
     723             :   // decide:
     724           0 :   return aFrame->GetSize().width >= aFrame->GetSize().height;
     725             : }
     726             : 
     727             : static nsIFrame*
     728           0 : GetBodyFrame(nsIFrame* aCanvasFrame)
     729             : {
     730           0 :   nsIContent* content = aCanvasFrame->GetContent();
     731           0 :   if (!content) {
     732           0 :     return nullptr;
     733             :   }
     734           0 :   nsIDocument* document = content->OwnerDoc();
     735           0 :   nsIContent* body = document->GetBodyElement();
     736           0 :   if (!body) {
     737           0 :     return nullptr;
     738             :   }
     739           0 :   return body->GetPrimaryFrame();
     740             : }
     741             : 
     742             : bool
     743           0 : nsNativeTheme::IsDarkBackground(nsIFrame* aFrame)
     744             : {
     745           0 :   nsIScrollableFrame* scrollFrame = nullptr;
     746           0 :   while (!scrollFrame && aFrame) {
     747           0 :     scrollFrame = aFrame->GetScrollTargetFrame();
     748           0 :     aFrame = aFrame->GetParent();
     749             :   }
     750           0 :   if (!scrollFrame)
     751           0 :     return false;
     752             : 
     753           0 :   nsIFrame* frame = scrollFrame->GetScrolledFrame();
     754           0 :   if (nsCSSRendering::IsCanvasFrame(frame)) {
     755             :     // For canvas frames, prefer to look at the body first, because the body
     756             :     // background color is most likely what will be visible as the background
     757             :     // color of the page, even if the html element has a different background
     758             :     // color which prevents that of the body frame to propagate to the viewport.
     759           0 :     nsIFrame* bodyFrame = GetBodyFrame(frame);
     760           0 :     if (bodyFrame) {
     761           0 :       frame = bodyFrame;
     762             :     }
     763             :   }
     764           0 :   nsStyleContext* bgSC = nullptr;
     765           0 :   if (!nsCSSRendering::FindBackground(frame, &bgSC) ||
     766           0 :       bgSC->StyleBackground()->IsTransparent(bgSC)) {
     767           0 :     nsIFrame* backgroundFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(frame, true);
     768           0 :     nsCSSRendering::FindBackground(backgroundFrame, &bgSC);
     769             :   }
     770           0 :   if (bgSC) {
     771           0 :     nscolor bgColor = bgSC->StyleBackground()->BackgroundColor(bgSC);
     772             :     // Consider the background color dark if the sum of the r, g and b values is
     773             :     // less than 384 in a semi-transparent document.  This heuristic matches what
     774             :     // WebKit does, and we can improve it later if needed.
     775           0 :     return NS_GET_A(bgColor) > 127 &&
     776           0 :            NS_GET_R(bgColor) + NS_GET_G(bgColor) + NS_GET_B(bgColor) < 384;
     777             :   }
     778           0 :   return false;
     779             : }

Generated by: LCOV version 1.13