LCOV - code coverage report
Current view: directory - widget/gtk2 - nsNativeThemeGTK.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 574 0 0.0 %
Date: 2012-06-02 Functions: 32 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2002
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Brian Ryner <bryner@brianryner.com>  (Original Author)
      24                 :  *  Michael Ventnor <m.ventnor@gmail.com>
      25                 :  *  Teune van Steeg <t.vansteeg@gmail.com>
      26                 :  *  Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      30                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : #include "nsNativeThemeGTK.h"
      43                 : #include "nsThemeConstants.h"
      44                 : #include "gtkdrawing.h"
      45                 : 
      46                 : #include "nsIObserverService.h"
      47                 : #include "nsIServiceManager.h"
      48                 : #include "nsIFrame.h"
      49                 : #include "nsIPresShell.h"
      50                 : #include "nsIDocument.h"
      51                 : #include "nsIContent.h"
      52                 : #include "nsIViewManager.h"
      53                 : #include "nsINameSpaceManager.h"
      54                 : #include "nsGfxCIID.h"
      55                 : #include "nsTransform2D.h"
      56                 : #include "nsMenuFrame.h"
      57                 : #include "prlink.h"
      58                 : #include "nsIDOMHTMLInputElement.h"
      59                 : #include "nsRenderingContext.h"
      60                 : #include "nsGkAtoms.h"
      61                 : #include "mozilla/Services.h"
      62                 : 
      63                 : #include <gdk/gdkprivate.h>
      64                 : #include <gtk/gtk.h>
      65                 : 
      66                 : #include "gfxContext.h"
      67                 : #include "gfxPlatformGtk.h"
      68                 : #include "gfxGdkNativeRenderer.h"
      69                 : 
      70               0 : NS_IMPL_ISUPPORTS_INHERITED2(nsNativeThemeGTK, nsNativeTheme, nsITheme,
      71                 :                                                               nsIObserver)
      72                 : 
      73                 : static int gLastGdkError;
      74                 : 
      75               0 : nsNativeThemeGTK::nsNativeThemeGTK()
      76                 : {
      77               0 :   if (moz_gtk_init() != MOZ_GTK_SUCCESS) {
      78               0 :     memset(mDisabledWidgetTypes, 0xff, sizeof(mDisabledWidgetTypes));
      79               0 :     return;
      80                 :   }
      81                 : 
      82                 :   // We have to call moz_gtk_shutdown before the event loop stops running.
      83                 :   nsCOMPtr<nsIObserverService> obsServ =
      84               0 :     mozilla::services::GetObserverService();
      85               0 :   obsServ->AddObserver(this, "xpcom-shutdown", false);
      86                 : 
      87               0 :   memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes));
      88               0 :   memset(mSafeWidgetStates, 0, sizeof(mSafeWidgetStates));
      89                 : }
      90                 : 
      91               0 : nsNativeThemeGTK::~nsNativeThemeGTK() {
      92               0 : }
      93                 : 
      94                 : NS_IMETHODIMP
      95               0 : nsNativeThemeGTK::Observe(nsISupports *aSubject, const char *aTopic,
      96                 :                           const PRUnichar *aData)
      97                 : {
      98               0 :   if (!nsCRT::strcmp(aTopic, "xpcom-shutdown")) {
      99               0 :     moz_gtk_shutdown();
     100                 :   } else {
     101               0 :     NS_NOTREACHED("unexpected topic");
     102               0 :     return NS_ERROR_UNEXPECTED;
     103                 :   }
     104                 : 
     105               0 :   return NS_OK;
     106                 : }
     107                 : 
     108                 : void
     109               0 : nsNativeThemeGTK::RefreshWidgetWindow(nsIFrame* aFrame)
     110                 : {
     111               0 :   nsIPresShell *shell = GetPresShell(aFrame);
     112               0 :   if (!shell)
     113               0 :     return;
     114                 : 
     115               0 :   nsIViewManager* vm = shell->GetViewManager();
     116               0 :   if (!vm)
     117               0 :     return;
     118                 :  
     119               0 :   vm->InvalidateAllViews();
     120                 : }
     121                 : 
     122               0 : static bool IsFrameContentNodeInNamespace(nsIFrame *aFrame, PRUint32 aNamespace)
     123                 : {
     124               0 :   nsIContent *content = aFrame ? aFrame->GetContent() : nsnull;
     125               0 :   if (!content)
     126               0 :     return false;
     127               0 :   return content->IsInNamespace(aNamespace);
     128                 : }
     129                 : 
     130               0 : static bool IsWidgetTypeDisabled(PRUint8* aDisabledVector, PRUint8 aWidgetType) {
     131               0 :   return (aDisabledVector[aWidgetType >> 3] & (1 << (aWidgetType & 7))) != 0;
     132                 : }
     133                 : 
     134               0 : static void SetWidgetTypeDisabled(PRUint8* aDisabledVector, PRUint8 aWidgetType) {
     135               0 :   aDisabledVector[aWidgetType >> 3] |= (1 << (aWidgetType & 7));
     136               0 : }
     137                 : 
     138                 : static inline PRUint16
     139               0 : GetWidgetStateKey(PRUint8 aWidgetType, GtkWidgetState *aWidgetState)
     140                 : {
     141                 :   return (aWidgetState->active |
     142                 :           aWidgetState->focused << 1 |
     143                 :           aWidgetState->inHover << 2 |
     144                 :           aWidgetState->disabled << 3 |
     145                 :           aWidgetState->isDefault << 4 |
     146               0 :           aWidgetType << 5);
     147                 : }
     148                 : 
     149               0 : static bool IsWidgetStateSafe(PRUint8* aSafeVector,
     150                 :                                 PRUint8 aWidgetType,
     151                 :                                 GtkWidgetState *aWidgetState)
     152                 : {
     153               0 :   PRUint8 key = GetWidgetStateKey(aWidgetType, aWidgetState);
     154               0 :   return (aSafeVector[key >> 3] & (1 << (key & 7))) != 0;
     155                 : }
     156                 : 
     157               0 : static void SetWidgetStateSafe(PRUint8 *aSafeVector,
     158                 :                                PRUint8 aWidgetType,
     159                 :                                GtkWidgetState *aWidgetState)
     160                 : {
     161               0 :   PRUint8 key = GetWidgetStateKey(aWidgetType, aWidgetState);
     162               0 :   aSafeVector[key >> 3] |= (1 << (key & 7));
     163               0 : }
     164                 : 
     165               0 : static GtkTextDirection GetTextDirection(nsIFrame* aFrame)
     166                 : {
     167               0 :   if (!aFrame)
     168               0 :     return GTK_TEXT_DIR_NONE;
     169                 : 
     170               0 :   switch (aFrame->GetStyleVisibility()->mDirection) {
     171                 :     case NS_STYLE_DIRECTION_RTL:
     172               0 :       return GTK_TEXT_DIR_RTL;
     173                 :     case NS_STYLE_DIRECTION_LTR:
     174               0 :       return GTK_TEXT_DIR_LTR;
     175                 :   }
     176                 : 
     177               0 :   return GTK_TEXT_DIR_NONE;
     178                 : }
     179                 : 
     180                 : // Returns positive for negative margins (otherwise 0).
     181                 : gint
     182               0 : nsNativeThemeGTK::GetTabMarginPixels(nsIFrame* aFrame)
     183                 : {
     184                 :   nscoord margin =
     185               0 :     IsBottomTab(aFrame) ? aFrame->GetUsedMargin().top
     186               0 :     : aFrame->GetUsedMargin().bottom;
     187                 : 
     188                 :   return NS_MIN<gint>(MOZ_GTK_TAB_MARGIN_MASK,
     189                 :                 NS_MAX(0,
     190               0 :                        aFrame->PresContext()->AppUnitsToDevPixels(-margin)));
     191                 : }
     192                 : 
     193                 : bool
     194               0 : nsNativeThemeGTK::GetGtkWidgetAndState(PRUint8 aWidgetType, nsIFrame* aFrame,
     195                 :                                        GtkThemeWidgetType& aGtkWidgetType,
     196                 :                                        GtkWidgetState* aState,
     197                 :                                        gint* aWidgetFlags)
     198                 : {
     199               0 :   if (aState) {
     200               0 :     if (!aFrame) {
     201                 :       // reset the entire struct to zero
     202               0 :       memset(aState, 0, sizeof(GtkWidgetState));
     203                 :     } else {
     204                 : 
     205                 :       // For XUL checkboxes and radio buttons, the state of the parent
     206                 :       // determines our state.
     207               0 :       nsIFrame *stateFrame = aFrame;
     208               0 :       if (aFrame && ((aWidgetFlags && (aWidgetType == NS_THEME_CHECKBOX ||
     209                 :                                        aWidgetType == NS_THEME_RADIO)) ||
     210                 :                      aWidgetType == NS_THEME_CHECKBOX_LABEL ||
     211                 :                      aWidgetType == NS_THEME_RADIO_LABEL)) {
     212                 : 
     213               0 :         nsIAtom* atom = nsnull;
     214               0 :         if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
     215               0 :           if (aWidgetType == NS_THEME_CHECKBOX_LABEL ||
     216                 :               aWidgetType == NS_THEME_RADIO_LABEL) {
     217                 :             // Adjust stateFrame so GetContentState finds the correct state.
     218               0 :             stateFrame = aFrame = aFrame->GetParent()->GetParent();
     219                 :           } else {
     220                 :             // GetContentState knows to look one frame up for radio/checkbox
     221                 :             // widgets, so don't adjust stateFrame here.
     222               0 :             aFrame = aFrame->GetParent();
     223                 :           }
     224               0 :           if (aWidgetFlags) {
     225               0 :             if (!atom) {
     226                 :               atom = (aWidgetType == NS_THEME_CHECKBOX ||
     227                 :                       aWidgetType == NS_THEME_CHECKBOX_LABEL) ? nsGkAtoms::checked
     228               0 :                                                               : nsGkAtoms::selected;
     229                 :             }
     230               0 :             *aWidgetFlags = CheckBooleanAttr(aFrame, atom);
     231                 :           }
     232                 :         } else {
     233               0 :           if (aWidgetFlags) {
     234               0 :             nsCOMPtr<nsIDOMHTMLInputElement> inputElt(do_QueryInterface(aFrame->GetContent()));
     235               0 :             *aWidgetFlags = 0;
     236               0 :             if (inputElt) {
     237                 :               bool isHTMLChecked;
     238               0 :               inputElt->GetChecked(&isHTMLChecked);
     239               0 :               if (isHTMLChecked)
     240               0 :                 *aWidgetFlags |= MOZ_GTK_WIDGET_CHECKED;
     241                 :             }
     242                 : 
     243               0 :             if (GetIndeterminate(aFrame))
     244               0 :               *aWidgetFlags |= MOZ_GTK_WIDGET_INCONSISTENT;
     245                 :           }
     246               0 :         }
     247               0 :       } else if (aWidgetType == NS_THEME_TOOLBAR_BUTTON_DROPDOWN ||
     248                 :                  aWidgetType == NS_THEME_TREEVIEW_HEADER_SORTARROW ||
     249                 :                  aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS ||
     250                 :                  aWidgetType == NS_THEME_BUTTON_ARROW_NEXT ||
     251                 :                  aWidgetType == NS_THEME_BUTTON_ARROW_UP ||
     252                 :                  aWidgetType == NS_THEME_BUTTON_ARROW_DOWN) {
     253                 :         // The state of an arrow comes from its parent.
     254               0 :         stateFrame = aFrame = aFrame->GetParent();
     255                 :       }
     256                 : 
     257               0 :       nsEventStates eventState = GetContentState(stateFrame, aWidgetType);
     258                 : 
     259               0 :       aState->disabled = IsDisabled(aFrame, eventState) || IsReadOnly(aFrame);
     260               0 :       aState->active  = eventState.HasState(NS_EVENT_STATE_ACTIVE);
     261               0 :       aState->focused = eventState.HasState(NS_EVENT_STATE_FOCUS);
     262               0 :       aState->inHover = eventState.HasState(NS_EVENT_STATE_HOVER);
     263               0 :       aState->isDefault = IsDefaultButton(aFrame);
     264               0 :       aState->canDefault = FALSE; // XXX fix me
     265               0 :       aState->depressed = FALSE;
     266                 : 
     267               0 :       if (IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) {
     268                 :         // For these widget types, some element (either a child or parent)
     269                 :         // actually has element focus, so we check the focused attribute
     270                 :         // to see whether to draw in the focused state.
     271               0 :         if (aWidgetType == NS_THEME_TEXTFIELD ||
     272                 :             aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
     273                 :             aWidgetType == NS_THEME_DROPDOWN_TEXTFIELD ||
     274                 :             aWidgetType == NS_THEME_SPINNER_TEXTFIELD ||
     275                 :             aWidgetType == NS_THEME_RADIO_CONTAINER ||
     276                 :             aWidgetType == NS_THEME_RADIO_LABEL) {
     277               0 :           aState->focused = IsFocused(aFrame);
     278               0 :         } else if (aWidgetType == NS_THEME_RADIO ||
     279                 :                    aWidgetType == NS_THEME_CHECKBOX) {
     280                 :           // In XUL, checkboxes and radios shouldn't have focus rings, their labels do
     281               0 :           aState->focused = FALSE;
     282                 :         }
     283                 : 
     284               0 :         if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL ||
     285                 :             aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) {
     286                 :           // for scrollbars we need to go up two to go from the thumb to
     287                 :           // the slider to the actual scrollbar object
     288               0 :           nsIFrame *tmpFrame = aFrame->GetParent()->GetParent();
     289                 : 
     290               0 :           aState->curpos = CheckIntAttr(tmpFrame, nsGkAtoms::curpos, 0);
     291               0 :           aState->maxpos = CheckIntAttr(tmpFrame, nsGkAtoms::maxpos, 100);
     292                 :         }
     293                 : 
     294               0 :         if (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_UP ||
     295                 :             aWidgetType == NS_THEME_SCROLLBAR_BUTTON_DOWN ||
     296                 :             aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT ||
     297                 :             aWidgetType == NS_THEME_SCROLLBAR_BUTTON_RIGHT) {
     298                 :           // set the state to disabled when the scrollbar is scrolled to
     299                 :           // the beginning or the end, depending on the button type.
     300               0 :           PRInt32 curpos = CheckIntAttr(aFrame, nsGkAtoms::curpos, 0);
     301               0 :           PRInt32 maxpos = CheckIntAttr(aFrame, nsGkAtoms::maxpos, 100);
     302               0 :           if ((curpos == 0 && (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_UP ||
     303                 :                 aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT)) ||
     304                 :               (curpos == maxpos &&
     305                 :                (aWidgetType == NS_THEME_SCROLLBAR_BUTTON_DOWN ||
     306                 :                 aWidgetType == NS_THEME_SCROLLBAR_BUTTON_RIGHT)))
     307               0 :             aState->disabled = true;
     308                 : 
     309                 :           // In order to simulate native GTK scrollbar click behavior,
     310                 :           // we set the active attribute on the element to true if it's
     311                 :           // pressed with any mouse button.
     312                 :           // This allows us to show that it's active without setting :active
     313               0 :           else if (CheckBooleanAttr(aFrame, nsGkAtoms::active))
     314               0 :             aState->active = true;
     315                 : 
     316               0 :           if (aWidgetFlags) {
     317               0 :             *aWidgetFlags = GetScrollbarButtonType(aFrame);
     318               0 :             if (aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP < 2)
     319               0 :               *aWidgetFlags |= MOZ_GTK_STEPPER_VERTICAL;
     320                 :           }
     321                 :         }
     322                 : 
     323                 :         // menu item state is determined by the attribute "_moz-menuactive",
     324                 :         // and not by the mouse hovering (accessibility).  as a special case,
     325                 :         // menus which are children of a menu bar are only marked as prelight
     326                 :         // if they are open, not on normal hover.
     327                 : 
     328               0 :         if (aWidgetType == NS_THEME_MENUITEM ||
     329                 :             aWidgetType == NS_THEME_CHECKMENUITEM ||
     330                 :             aWidgetType == NS_THEME_RADIOMENUITEM ||
     331                 :             aWidgetType == NS_THEME_MENUSEPARATOR ||
     332                 :             aWidgetType == NS_THEME_MENUARROW) {
     333               0 :           bool isTopLevel = false;
     334               0 :           nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
     335               0 :           if (menuFrame) {
     336               0 :             isTopLevel = menuFrame->IsOnMenuBar();
     337                 :           }
     338                 : 
     339               0 :           if (isTopLevel) {
     340               0 :             aState->inHover = menuFrame->IsOpen();
     341               0 :             *aWidgetFlags |= MOZ_TOPLEVEL_MENU_ITEM;
     342                 :           } else {
     343               0 :             aState->inHover = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
     344               0 :             *aWidgetFlags &= ~MOZ_TOPLEVEL_MENU_ITEM;
     345                 :           }
     346                 : 
     347               0 :           aState->active = FALSE;
     348                 :         
     349               0 :           if (aWidgetType == NS_THEME_CHECKMENUITEM ||
     350                 :               aWidgetType == NS_THEME_RADIOMENUITEM) {
     351               0 :             *aWidgetFlags = 0;
     352               0 :             if (aFrame && aFrame->GetContent()) {
     353               0 :               *aWidgetFlags = aFrame->GetContent()->
     354                 :                 AttrValueIs(kNameSpaceID_None, nsGkAtoms::checked,
     355               0 :                             nsGkAtoms::_true, eIgnoreCase);
     356                 :             }
     357                 :           }
     358                 :         }
     359                 : 
     360                 :         // A button with drop down menu open or an activated toggle button
     361                 :         // should always appear depressed.
     362               0 :         if (aWidgetType == NS_THEME_BUTTON ||
     363                 :             aWidgetType == NS_THEME_TOOLBAR_BUTTON ||
     364                 :             aWidgetType == NS_THEME_TOOLBAR_DUAL_BUTTON ||
     365                 :             aWidgetType == NS_THEME_TOOLBAR_BUTTON_DROPDOWN ||
     366                 :             aWidgetType == NS_THEME_DROPDOWN ||
     367                 :             aWidgetType == NS_THEME_DROPDOWN_BUTTON) {
     368               0 :           bool menuOpen = IsOpenButton(aFrame);
     369               0 :           aState->depressed = IsCheckedButton(aFrame) || menuOpen;
     370                 :           // we must not highlight buttons with open drop down menus on hover.
     371               0 :           aState->inHover = aState->inHover && !menuOpen;
     372                 :         }
     373                 : 
     374                 :         // When the input field of the drop down button has focus, some themes
     375                 :         // should draw focus for the drop down button as well.
     376               0 :         if (aWidgetType == NS_THEME_DROPDOWN_BUTTON && aWidgetFlags) {
     377               0 :           *aWidgetFlags = CheckBooleanAttr(aFrame, nsGkAtoms::parentfocused);
     378                 :         }
     379                 :       }
     380                 :     }
     381                 :   }
     382                 : 
     383               0 :   switch (aWidgetType) {
     384                 :   case NS_THEME_BUTTON:
     385                 :   case NS_THEME_TOOLBAR_BUTTON:
     386                 :   case NS_THEME_TOOLBAR_DUAL_BUTTON:
     387               0 :     if (aWidgetFlags)
     388               0 :       *aWidgetFlags = (aWidgetType == NS_THEME_BUTTON) ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE;
     389               0 :     aGtkWidgetType = MOZ_GTK_BUTTON;
     390               0 :     break;
     391                 :   case NS_THEME_CHECKBOX:
     392                 :   case NS_THEME_RADIO:
     393               0 :     aGtkWidgetType = (aWidgetType == NS_THEME_RADIO) ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON;
     394               0 :     break;
     395                 :   case NS_THEME_SCROLLBAR_BUTTON_UP:
     396                 :   case NS_THEME_SCROLLBAR_BUTTON_DOWN:
     397                 :   case NS_THEME_SCROLLBAR_BUTTON_LEFT:
     398                 :   case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
     399               0 :     aGtkWidgetType = MOZ_GTK_SCROLLBAR_BUTTON;
     400               0 :     break;
     401                 :   case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
     402               0 :     aGtkWidgetType = MOZ_GTK_SCROLLBAR_TRACK_VERTICAL;
     403               0 :     break;
     404                 :   case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
     405               0 :     aGtkWidgetType = MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL;
     406               0 :     break;
     407                 :   case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
     408               0 :     aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL;
     409               0 :     break;
     410                 :   case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
     411               0 :     aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL;
     412               0 :     break;
     413                 :   case NS_THEME_SPINNER:
     414               0 :     aGtkWidgetType = MOZ_GTK_SPINBUTTON;
     415               0 :     break;
     416                 :   case NS_THEME_SPINNER_UP_BUTTON:
     417               0 :     aGtkWidgetType = MOZ_GTK_SPINBUTTON_UP;
     418               0 :     break;
     419                 :   case NS_THEME_SPINNER_DOWN_BUTTON:
     420               0 :     aGtkWidgetType = MOZ_GTK_SPINBUTTON_DOWN;
     421               0 :     break;
     422                 :   case NS_THEME_SPINNER_TEXTFIELD:
     423               0 :     aGtkWidgetType = MOZ_GTK_SPINBUTTON_ENTRY;
     424               0 :     break;
     425                 :   case NS_THEME_SCALE_HORIZONTAL:
     426               0 :     if (aWidgetFlags)
     427               0 :       *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL;
     428               0 :     aGtkWidgetType = MOZ_GTK_SCALE_HORIZONTAL;
     429               0 :     break;
     430                 :   case NS_THEME_SCALE_THUMB_HORIZONTAL:
     431               0 :     if (aWidgetFlags)
     432               0 :       *aWidgetFlags = GTK_ORIENTATION_HORIZONTAL;
     433               0 :     aGtkWidgetType = MOZ_GTK_SCALE_THUMB_HORIZONTAL;
     434               0 :     break;
     435                 :   case NS_THEME_SCALE_VERTICAL:
     436               0 :     if (aWidgetFlags)
     437               0 :       *aWidgetFlags = GTK_ORIENTATION_VERTICAL;
     438               0 :     aGtkWidgetType = MOZ_GTK_SCALE_VERTICAL;
     439               0 :     break;
     440                 :   case NS_THEME_TOOLBAR_SEPARATOR:
     441               0 :     aGtkWidgetType = MOZ_GTK_TOOLBAR_SEPARATOR;
     442               0 :     break;
     443                 :   case NS_THEME_SCALE_THUMB_VERTICAL:
     444               0 :     if (aWidgetFlags)
     445               0 :       *aWidgetFlags = GTK_ORIENTATION_VERTICAL;
     446               0 :     aGtkWidgetType = MOZ_GTK_SCALE_THUMB_VERTICAL;
     447               0 :     break;
     448                 :   case NS_THEME_TOOLBAR_GRIPPER:
     449               0 :     aGtkWidgetType = MOZ_GTK_GRIPPER;
     450               0 :     break;
     451                 :   case NS_THEME_RESIZER:
     452               0 :     aGtkWidgetType = MOZ_GTK_RESIZER;
     453               0 :     break;
     454                 :   case NS_THEME_TEXTFIELD:
     455                 :   case NS_THEME_TEXTFIELD_MULTILINE:
     456               0 :     aGtkWidgetType = MOZ_GTK_ENTRY;
     457               0 :     break;
     458                 :   case NS_THEME_TEXTFIELD_CARET:
     459               0 :     aGtkWidgetType = MOZ_GTK_ENTRY_CARET;
     460               0 :     break;
     461                 :   case NS_THEME_LISTBOX:
     462                 :   case NS_THEME_TREEVIEW:
     463               0 :     aGtkWidgetType = MOZ_GTK_TREEVIEW;
     464               0 :     break;
     465                 :   case NS_THEME_TREEVIEW_HEADER_CELL:
     466               0 :     if (aWidgetFlags) {
     467                 :       // In this case, the flag denotes whether the header is the sorted one or not
     468               0 :       if (GetTreeSortDirection(aFrame) == eTreeSortDirection_Natural)
     469               0 :         *aWidgetFlags = false;
     470                 :       else
     471               0 :         *aWidgetFlags = true;
     472                 :     }
     473               0 :     aGtkWidgetType = MOZ_GTK_TREE_HEADER_CELL;
     474               0 :     break;
     475                 :   case NS_THEME_TREEVIEW_HEADER_SORTARROW:
     476               0 :     if (aWidgetFlags) {
     477               0 :       switch (GetTreeSortDirection(aFrame)) {
     478                 :         case eTreeSortDirection_Ascending:
     479               0 :           *aWidgetFlags = GTK_ARROW_DOWN;
     480               0 :           break;
     481                 :         case eTreeSortDirection_Descending:
     482               0 :           *aWidgetFlags = GTK_ARROW_UP;
     483               0 :           break;
     484                 :         case eTreeSortDirection_Natural:
     485                 :         default:
     486                 :           /* GTK_ARROW_NONE is implemented since GTK 2.10
     487                 :            * This prevents the treecolums from getting smaller
     488                 :            * and wider when switching sort direction off and on
     489                 :            * */
     490                 : #if GTK_CHECK_VERSION(2,10,0)
     491               0 :           *aWidgetFlags = GTK_ARROW_NONE;
     492                 : #else
     493                 :           return false; // Don't draw when we shouldn't
     494                 : #endif // GTK_CHECK_VERSION(2,10,0)
     495               0 :           break;
     496                 :       }
     497                 :     }
     498               0 :     aGtkWidgetType = MOZ_GTK_TREE_HEADER_SORTARROW;
     499               0 :     break;
     500                 :   case NS_THEME_TREEVIEW_TWISTY:
     501               0 :     aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER;
     502               0 :     if (aWidgetFlags)
     503               0 :       *aWidgetFlags = GTK_EXPANDER_COLLAPSED;
     504               0 :     break;
     505                 :   case NS_THEME_TREEVIEW_TWISTY_OPEN:
     506               0 :     aGtkWidgetType = MOZ_GTK_TREEVIEW_EXPANDER;
     507               0 :     if (aWidgetFlags)
     508               0 :       *aWidgetFlags = GTK_EXPANDER_EXPANDED;
     509               0 :     break;
     510                 :   case NS_THEME_DROPDOWN:
     511               0 :     aGtkWidgetType = MOZ_GTK_DROPDOWN;
     512               0 :     if (aWidgetFlags)
     513               0 :         *aWidgetFlags = IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML);
     514               0 :     break;
     515                 :   case NS_THEME_DROPDOWN_TEXT:
     516               0 :     return false; // nothing to do, but prevents the bg from being drawn
     517                 :   case NS_THEME_DROPDOWN_TEXTFIELD:
     518               0 :     aGtkWidgetType = MOZ_GTK_DROPDOWN_ENTRY;
     519               0 :     break;
     520                 :   case NS_THEME_DROPDOWN_BUTTON:
     521               0 :     aGtkWidgetType = MOZ_GTK_DROPDOWN_ARROW;
     522               0 :     break;
     523                 :   case NS_THEME_TOOLBAR_BUTTON_DROPDOWN:
     524                 :   case NS_THEME_BUTTON_ARROW_DOWN:
     525                 :   case NS_THEME_BUTTON_ARROW_UP:
     526                 :   case NS_THEME_BUTTON_ARROW_NEXT:
     527                 :   case NS_THEME_BUTTON_ARROW_PREVIOUS:
     528               0 :     aGtkWidgetType = MOZ_GTK_TOOLBARBUTTON_ARROW;
     529               0 :     if (aWidgetFlags) {
     530               0 :       *aWidgetFlags = GTK_ARROW_DOWN;
     531                 : 
     532               0 :       if (aWidgetType == NS_THEME_BUTTON_ARROW_UP)
     533               0 :         *aWidgetFlags = GTK_ARROW_UP;
     534               0 :       else if (aWidgetType == NS_THEME_BUTTON_ARROW_NEXT)
     535               0 :         *aWidgetFlags = GTK_ARROW_RIGHT;
     536               0 :       else if (aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS)
     537               0 :         *aWidgetFlags = GTK_ARROW_LEFT;
     538                 :     }
     539               0 :     break;
     540                 :   case NS_THEME_CHECKBOX_CONTAINER:
     541               0 :     aGtkWidgetType = MOZ_GTK_CHECKBUTTON_CONTAINER;
     542               0 :     break;
     543                 :   case NS_THEME_RADIO_CONTAINER:
     544               0 :     aGtkWidgetType = MOZ_GTK_RADIOBUTTON_CONTAINER;
     545               0 :     break;
     546                 :   case NS_THEME_CHECKBOX_LABEL:
     547               0 :     aGtkWidgetType = MOZ_GTK_CHECKBUTTON_LABEL;
     548               0 :     break;
     549                 :   case NS_THEME_RADIO_LABEL:
     550               0 :     aGtkWidgetType = MOZ_GTK_RADIOBUTTON_LABEL;
     551               0 :     break;
     552                 :   case NS_THEME_TOOLBAR:
     553               0 :     aGtkWidgetType = MOZ_GTK_TOOLBAR;
     554               0 :     break;
     555                 :   case NS_THEME_TOOLTIP:
     556               0 :     aGtkWidgetType = MOZ_GTK_TOOLTIP;
     557               0 :     break;
     558                 :   case NS_THEME_STATUSBAR_PANEL:
     559                 :   case NS_THEME_STATUSBAR_RESIZER_PANEL:
     560               0 :     aGtkWidgetType = MOZ_GTK_FRAME;
     561               0 :     break;
     562                 :   case NS_THEME_PROGRESSBAR:
     563                 :   case NS_THEME_PROGRESSBAR_VERTICAL:
     564               0 :     aGtkWidgetType = MOZ_GTK_PROGRESSBAR;
     565               0 :     break;
     566                 :   case NS_THEME_PROGRESSBAR_CHUNK:
     567                 :   case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
     568                 :     {
     569               0 :       nsIFrame* stateFrame = aFrame->GetParent();
     570               0 :       nsEventStates eventStates = GetContentState(stateFrame, aWidgetType);
     571                 : 
     572               0 :       aGtkWidgetType = IsIndeterminateProgress(stateFrame, eventStates)
     573               0 :                          ? (stateFrame->GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL)
     574                 :                            ? MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE
     575                 :                            : MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE
     576               0 :                          : MOZ_GTK_PROGRESS_CHUNK;
     577                 :     }
     578               0 :     break;
     579                 :   case NS_THEME_TAB_SCROLLARROW_BACK:
     580                 :   case NS_THEME_TAB_SCROLLARROW_FORWARD:
     581               0 :     if (aWidgetFlags)
     582                 :       *aWidgetFlags = aWidgetType == NS_THEME_TAB_SCROLLARROW_BACK ?
     583               0 :                         GTK_ARROW_LEFT : GTK_ARROW_RIGHT;
     584               0 :     aGtkWidgetType = MOZ_GTK_TAB_SCROLLARROW;
     585               0 :     break;
     586                 :   case NS_THEME_TAB_PANELS:
     587               0 :     aGtkWidgetType = MOZ_GTK_TABPANELS;
     588               0 :     break;
     589                 :   case NS_THEME_TAB:
     590                 :     {
     591               0 :       if (aWidgetFlags) {
     592                 :         /* First bits will be used to store max(0,-bmargin) where bmargin
     593                 :          * is the bottom margin of the tab in pixels  (resp. top margin,
     594                 :          * for bottom tabs). */
     595               0 :         if (IsBottomTab(aFrame)) {
     596               0 :             *aWidgetFlags = MOZ_GTK_TAB_BOTTOM;
     597                 :         } else {
     598               0 :             *aWidgetFlags = 0;
     599                 :         }
     600                 : 
     601               0 :         *aWidgetFlags |= GetTabMarginPixels(aFrame);
     602                 : 
     603               0 :         if (IsSelectedTab(aFrame))
     604               0 :           *aWidgetFlags |= MOZ_GTK_TAB_SELECTED;
     605                 : 
     606               0 :         if (IsFirstTab(aFrame))
     607               0 :           *aWidgetFlags |= MOZ_GTK_TAB_FIRST;
     608                 :       }
     609                 : 
     610               0 :       aGtkWidgetType = MOZ_GTK_TAB;
     611                 :     }
     612               0 :     break;
     613                 :   case NS_THEME_SPLITTER:
     614               0 :     if (IsHorizontal(aFrame))
     615               0 :       aGtkWidgetType = MOZ_GTK_SPLITTER_VERTICAL;
     616                 :     else 
     617               0 :       aGtkWidgetType = MOZ_GTK_SPLITTER_HORIZONTAL;
     618               0 :     break;
     619                 :   case NS_THEME_MENUBAR:
     620               0 :     aGtkWidgetType = MOZ_GTK_MENUBAR;
     621               0 :     break;
     622                 :   case NS_THEME_MENUPOPUP:
     623               0 :     aGtkWidgetType = MOZ_GTK_MENUPOPUP;
     624               0 :     break;
     625                 :   case NS_THEME_MENUITEM:
     626               0 :     aGtkWidgetType = MOZ_GTK_MENUITEM;
     627               0 :     break;
     628                 :   case NS_THEME_MENUSEPARATOR:
     629               0 :     aGtkWidgetType = MOZ_GTK_MENUSEPARATOR;
     630               0 :     break;
     631                 :   case NS_THEME_MENUARROW:
     632               0 :     aGtkWidgetType = MOZ_GTK_MENUARROW;
     633               0 :     break;
     634                 :   case NS_THEME_CHECKMENUITEM:
     635               0 :     aGtkWidgetType = MOZ_GTK_CHECKMENUITEM;
     636               0 :     break;
     637                 :   case NS_THEME_RADIOMENUITEM:
     638               0 :     aGtkWidgetType = MOZ_GTK_RADIOMENUITEM;
     639               0 :     break;
     640                 :   case NS_THEME_WINDOW:
     641                 :   case NS_THEME_DIALOG:
     642               0 :     aGtkWidgetType = MOZ_GTK_WINDOW;
     643               0 :     break;
     644                 :   default:
     645               0 :     return false;
     646                 :   }
     647                 : 
     648               0 :   return true;
     649                 : }
     650                 : 
     651                 : class ThemeRenderer : public gfxGdkNativeRenderer {
     652                 : public:
     653               0 :   ThemeRenderer(GtkWidgetState aState, GtkThemeWidgetType aGTKWidgetType,
     654                 :                 gint aFlags, GtkTextDirection aDirection,
     655                 :                 const GdkRectangle& aGDKRect, const GdkRectangle& aGDKClip)
     656                 :     : mState(aState), mGTKWidgetType(aGTKWidgetType), mFlags(aFlags),
     657               0 :       mDirection(aDirection), mGDKRect(aGDKRect), mGDKClip(aGDKClip) {}
     658                 :   nsresult DrawWithGDK(GdkDrawable * drawable, gint offsetX, gint offsetY,
     659                 :                        GdkRectangle * clipRects, PRUint32 numClipRects);
     660                 : private:
     661                 :   GtkWidgetState mState;
     662                 :   GtkThemeWidgetType mGTKWidgetType;
     663                 :   gint mFlags;
     664                 :   GtkTextDirection mDirection;
     665                 :   GdkWindow* mWindow;
     666                 :   const GdkRectangle& mGDKRect;
     667                 :   const GdkRectangle& mGDKClip;
     668                 : };
     669                 : 
     670                 : nsresult
     671               0 : ThemeRenderer::DrawWithGDK(GdkDrawable * drawable, gint offsetX, 
     672                 :         gint offsetY, GdkRectangle * clipRects, PRUint32 numClipRects)
     673                 : {
     674               0 :   GdkRectangle gdk_rect = mGDKRect;
     675               0 :   gdk_rect.x += offsetX;
     676               0 :   gdk_rect.y += offsetY;
     677                 : 
     678               0 :   GdkRectangle gdk_clip = mGDKClip;
     679               0 :   gdk_clip.x += offsetX;
     680               0 :   gdk_clip.y += offsetY;
     681                 : 
     682                 :   GdkRectangle surfaceRect;
     683               0 :   surfaceRect.x = 0;
     684               0 :   surfaceRect.y = 0;
     685               0 :   gdk_drawable_get_size(drawable, &surfaceRect.width, &surfaceRect.height);
     686               0 :   gdk_rectangle_intersect(&gdk_clip, &surfaceRect, &gdk_clip);
     687                 :   
     688               0 :   NS_ASSERTION(numClipRects == 0, "We don't support clipping!!!");
     689                 :   moz_gtk_widget_paint(mGTKWidgetType, drawable, &gdk_rect, &gdk_clip,
     690               0 :                        &mState, mFlags, mDirection);
     691                 : 
     692               0 :   return NS_OK;
     693                 : }
     694                 : 
     695                 : bool
     696               0 : nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, PRUint8 aWidgetType,
     697                 :                                         nsIntMargin* aExtra)
     698                 : {
     699               0 :   *aExtra = nsIntMargin(0,0,0,0);
     700                 :   // Allow an extra one pixel above and below the thumb for certain
     701                 :   // GTK2 themes (Ximian Industrial, Bluecurve, Misty, at least);
     702                 :   // We modify the frame's overflow area.  See bug 297508.
     703               0 :   switch (aWidgetType) {
     704                 :   case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
     705               0 :     aExtra->top = aExtra->bottom = 1;
     706               0 :     return true;
     707                 :   case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
     708               0 :     aExtra->left = aExtra->right = 1;
     709               0 :     return true;
     710                 : 
     711                 :   // Include the indicator spacing (the padding around the control).
     712                 :   case NS_THEME_CHECKBOX:
     713                 :   case NS_THEME_RADIO:
     714                 :     {
     715                 :       gint indicator_size, indicator_spacing;
     716                 : 
     717               0 :       if (aWidgetType == NS_THEME_CHECKBOX) {
     718               0 :         moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing);
     719                 :       } else {
     720               0 :         moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing);
     721                 :       }
     722                 : 
     723               0 :       aExtra->top = indicator_spacing;
     724               0 :       aExtra->right = indicator_spacing;
     725               0 :       aExtra->bottom = indicator_spacing;
     726               0 :       aExtra->left = indicator_spacing;
     727               0 :       return true;
     728                 :     }
     729                 :   case NS_THEME_BUTTON :
     730                 :     {
     731               0 :       if (IsDefaultButton(aFrame)) {
     732                 :         // Some themes draw a default indicator outside the widget,
     733                 :         // include that in overflow
     734                 :         gint top, left, bottom, right;
     735               0 :         moz_gtk_button_get_default_overflow(&top, &left, &bottom, &right);
     736               0 :         aExtra->top = top;
     737               0 :         aExtra->right = right;
     738               0 :         aExtra->bottom = bottom;
     739               0 :         aExtra->left = left;
     740               0 :         return true;
     741                 :       }
     742                 :     }
     743                 :   case NS_THEME_TAB :
     744                 :     {
     745               0 :       if (!IsSelectedTab(aFrame))
     746               0 :         return false;
     747                 : 
     748               0 :       gint gap_height = moz_gtk_get_tab_thickness();
     749                 : 
     750               0 :       PRInt32 extra = gap_height - GetTabMarginPixels(aFrame);
     751               0 :       if (extra <= 0)
     752               0 :         return false;
     753                 : 
     754               0 :       if (IsBottomTab(aFrame)) {
     755               0 :         aExtra->top = extra;
     756                 :       } else {
     757               0 :         aExtra->bottom = extra;
     758                 :       }
     759                 :     }
     760                 :   default:
     761               0 :     return false;
     762                 :   }
     763                 : }
     764                 : 
     765                 : NS_IMETHODIMP
     766               0 : nsNativeThemeGTK::DrawWidgetBackground(nsRenderingContext* aContext,
     767                 :                                        nsIFrame* aFrame,
     768                 :                                        PRUint8 aWidgetType,
     769                 :                                        const nsRect& aRect,
     770                 :                                        const nsRect& aDirtyRect)
     771                 : {
     772                 :   GtkWidgetState state;
     773                 :   GtkThemeWidgetType gtkWidgetType;
     774               0 :   GtkTextDirection direction = GetTextDirection(aFrame);
     775                 :   gint flags;
     776               0 :   if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, &state,
     777               0 :                             &flags))
     778               0 :     return NS_OK;
     779                 : 
     780               0 :   gfxContext* ctx = aContext->ThebesContext();
     781               0 :   nsPresContext *presContext = aFrame->PresContext();
     782                 : 
     783               0 :   gfxRect rect = presContext->AppUnitsToGfxUnits(aRect);
     784               0 :   gfxRect dirtyRect = presContext->AppUnitsToGfxUnits(aDirtyRect);
     785                 : 
     786                 :   // Align to device pixels where sensible
     787                 :   // to provide crisper and faster drawing.
     788                 :   // Don't snap if it's a non-unit scale factor. We're going to have to take
     789                 :   // slow paths then in any case.
     790               0 :   bool snapXY = ctx->UserToDevicePixelSnapped(rect);
     791               0 :   if (snapXY) {
     792                 :     // Leave rect in device coords but make dirtyRect consistent.
     793               0 :     dirtyRect = ctx->UserToDevice(dirtyRect);
     794                 :   }
     795                 : 
     796                 :   // Translate the dirty rect so that it is wrt the widget top-left.
     797               0 :   dirtyRect.MoveBy(-rect.TopLeft());
     798                 :   // Round out the dirty rect to gdk pixels to ensure that gtk draws
     799                 :   // enough pixels for interpolation to device pixels.
     800               0 :   dirtyRect.RoundOut();
     801                 : 
     802                 :   // GTK themes can only draw an integer number of pixels
     803                 :   // (even when not snapped).
     804               0 :   nsIntRect widgetRect(0, 0, NS_lround(rect.Width()), NS_lround(rect.Height()));
     805               0 :   nsIntRect overflowRect(widgetRect);
     806               0 :   nsIntMargin extraSize;
     807               0 :   if (GetExtraSizeForWidget(aFrame, aWidgetType, &extraSize)) {
     808               0 :     overflowRect.Inflate(extraSize);
     809                 :   }
     810                 : 
     811                 :   // This is the rectangle that will actually be drawn, in gdk pixels
     812               0 :   nsIntRect drawingRect(PRInt32(dirtyRect.X()),
     813               0 :                         PRInt32(dirtyRect.Y()),
     814               0 :                         PRInt32(dirtyRect.Width()),
     815               0 :                         PRInt32(dirtyRect.Height()));
     816               0 :   if (widgetRect.IsEmpty()
     817               0 :       || !drawingRect.IntersectRect(overflowRect, drawingRect))
     818               0 :     return NS_OK;
     819                 : 
     820                 :   // gdk rectangles are wrt the drawing rect.
     821                 : 
     822                 :   // The gdk_clip is just advisory here, meaning "you don't
     823                 :   // need to draw outside this rect if you don't feel like it!"
     824               0 :   GdkRectangle gdk_clip = {0, 0, drawingRect.width, drawingRect.height};
     825                 : 
     826                 :   GdkRectangle gdk_rect = {-drawingRect.x, -drawingRect.y,
     827               0 :                            widgetRect.width, widgetRect.height};
     828                 : 
     829                 :   ThemeRenderer renderer(state, gtkWidgetType, flags, direction,
     830               0 :                          gdk_rect, gdk_clip);
     831                 : 
     832                 :   // Some themes (e.g. Clearlooks) just don't clip properly to any
     833                 :   // clip rect we provide, so we cannot advertise support for clipping within
     834                 :   // the widget bounds.
     835               0 :   PRUint32 rendererFlags = 0;
     836               0 :   if (GetWidgetTransparency(aFrame, aWidgetType) == eOpaque) {
     837               0 :     rendererFlags |= gfxGdkNativeRenderer::DRAW_IS_OPAQUE;
     838                 :   }
     839                 : 
     840                 :   // translate everything so (0,0) is the top left of the drawingRect
     841               0 :   gfxContextAutoSaveRestore autoSR(ctx);
     842               0 :   if (snapXY) {
     843                 :     // Rects are in device coords.
     844               0 :     ctx->IdentityMatrix(); 
     845                 :   }
     846               0 :   ctx->Translate(rect.TopLeft() + gfxPoint(drawingRect.x, drawingRect.y));
     847                 : 
     848               0 :   NS_ASSERTION(!IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType),
     849                 :                "Trying to render an unsafe widget!");
     850                 : 
     851               0 :   bool safeState = IsWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state);
     852               0 :   if (!safeState) {
     853               0 :     gLastGdkError = 0;
     854               0 :     gdk_error_trap_push ();
     855                 :   }
     856                 : 
     857                 :   // GtkStyles (used by the widget drawing backend) are created for a
     858                 :   // particular colormap/visual.
     859               0 :   GdkColormap* colormap = moz_gtk_widget_get_colormap();
     860                 : 
     861               0 :   renderer.Draw(ctx, drawingRect.Size(), rendererFlags, colormap);
     862                 : 
     863               0 :   if (!safeState) {
     864               0 :     gdk_flush();
     865               0 :     gLastGdkError = gdk_error_trap_pop ();
     866                 : 
     867               0 :     if (gLastGdkError) {
     868                 : #ifdef DEBUG
     869                 :       printf("GTK theme failed for widget type %d, error was %d, state was "
     870                 :              "[active=%d,focused=%d,inHover=%d,disabled=%d]\n",
     871                 :              aWidgetType, gLastGdkError, state.active, state.focused,
     872               0 :              state.inHover, state.disabled);
     873                 : #endif
     874               0 :       NS_WARNING("GTK theme failed; disabling unsafe widget");
     875               0 :       SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType);
     876                 :       // force refresh of the window, because the widget was not
     877                 :       // successfully drawn it must be redrawn using the default look
     878               0 :       RefreshWidgetWindow(aFrame);
     879                 :     } else {
     880               0 :       SetWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state);
     881                 :     }
     882                 :   }
     883                 : 
     884                 :   // Indeterminate progress bar are animated.
     885               0 :   if (gtkWidgetType == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE ||
     886                 :       gtkWidgetType == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) {
     887               0 :     if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 30)) {
     888               0 :       NS_WARNING("unable to animate widget!");
     889                 :     }
     890                 :   }
     891                 : 
     892               0 :   return NS_OK;
     893                 : }
     894                 : 
     895                 : NS_IMETHODIMP
     896               0 : nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
     897                 :                                   PRUint8 aWidgetType, nsIntMargin* aResult)
     898                 : {
     899               0 :   GtkTextDirection direction = GetTextDirection(aFrame);
     900               0 :   aResult->top = aResult->left = aResult->right = aResult->bottom = 0;
     901               0 :   switch (aWidgetType) {
     902                 :   case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
     903                 :   case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
     904                 :     {
     905                 :       MozGtkScrollbarMetrics metrics;
     906               0 :       moz_gtk_get_scrollbar_metrics(&metrics);
     907               0 :       aResult->top = aResult->left = aResult->right = aResult->bottom = metrics.trough_border;
     908                 :     }
     909               0 :     break;
     910                 :   case NS_THEME_TOOLBOX:
     911                 :     // gtk has no toolbox equivalent.  So, although we map toolbox to
     912                 :     // gtk's 'toolbar' for purposes of painting the widget background,
     913                 :     // we don't use the toolbar border for toolbox.
     914               0 :     break;
     915                 :   case NS_THEME_TOOLBAR_DUAL_BUTTON:
     916                 :     // TOOLBAR_DUAL_BUTTON is an interesting case.  We want a border to draw
     917                 :     // around the entire button + dropdown, and also an inner border if you're
     918                 :     // over the button part.  But, we want the inner button to be right up
     919                 :     // against the edge of the outer button so that the borders overlap.
     920                 :     // To make this happen, we draw a button border for the outer button,
     921                 :     // but don't reserve any space for it.
     922               0 :     break;
     923                 :   case NS_THEME_TAB:
     924                 :     // Top tabs have no bottom border, bottom tabs have no top border
     925                 :     moz_gtk_get_widget_border(MOZ_GTK_TAB, &aResult->left, &aResult->top,
     926                 :                               &aResult->right, &aResult->bottom, direction,
     927               0 :                               FALSE);
     928               0 :     if (IsBottomTab(aFrame))
     929               0 :         aResult->top = 0;
     930                 :     else
     931               0 :         aResult->bottom = 0;
     932               0 :     break;
     933                 :   case NS_THEME_MENUITEM:
     934                 :   case NS_THEME_CHECKMENUITEM:
     935                 :   case NS_THEME_RADIOMENUITEM:
     936                 :     // For regular menuitems, we will be using GetWidgetPadding instead of
     937                 :     // GetWidgetBorder to pad up the widget's internals; other menuitems
     938                 :     // will need to fall through and use the default case as before.
     939               0 :     if (IsRegularMenuItem(aFrame))
     940               0 :       break;
     941                 :   default:
     942                 :     {
     943                 :       GtkThemeWidgetType gtkWidgetType;
     944               0 :       if (GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nsnull,
     945               0 :                                nsnull)) {
     946                 :         moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top,
     947                 :                                   &aResult->right, &aResult->bottom, direction,
     948               0 :                                   IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML));
     949                 :       }
     950                 :     }
     951                 :   }
     952               0 :   return NS_OK;
     953                 : }
     954                 : 
     955                 : bool
     956               0 : nsNativeThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
     957                 :                                    nsIFrame* aFrame, PRUint8 aWidgetType,
     958                 :                                    nsIntMargin* aResult)
     959                 : {
     960               0 :   switch (aWidgetType) {
     961                 :     case NS_THEME_BUTTON_FOCUS:
     962                 :     case NS_THEME_TOOLBAR_BUTTON:
     963                 :     case NS_THEME_TOOLBAR_DUAL_BUTTON:
     964                 :     case NS_THEME_TAB_SCROLLARROW_BACK:
     965                 :     case NS_THEME_TAB_SCROLLARROW_FORWARD:
     966                 :     case NS_THEME_DROPDOWN_BUTTON:
     967                 :     case NS_THEME_TOOLBAR_BUTTON_DROPDOWN:
     968                 :     case NS_THEME_BUTTON_ARROW_UP:
     969                 :     case NS_THEME_BUTTON_ARROW_DOWN:
     970                 :     case NS_THEME_BUTTON_ARROW_NEXT:
     971                 :     case NS_THEME_BUTTON_ARROW_PREVIOUS:
     972                 :     // Radios and checkboxes return a fixed size in GetMinimumWidgetSize
     973                 :     // and have a meaningful baseline, so they can't have
     974                 :     // author-specified padding.
     975                 :     case NS_THEME_CHECKBOX:
     976                 :     case NS_THEME_RADIO:
     977               0 :       aResult->SizeTo(0, 0, 0, 0);
     978               0 :       return true;
     979                 :     case NS_THEME_MENUITEM:
     980                 :     case NS_THEME_CHECKMENUITEM:
     981                 :     case NS_THEME_RADIOMENUITEM:
     982                 :       {
     983                 :         // Menubar and menulist have their padding specified in CSS.
     984               0 :         if (!IsRegularMenuItem(aFrame))
     985               0 :           return false;
     986                 : 
     987               0 :         aResult->SizeTo(0, 0, 0, 0);
     988                 :         GtkThemeWidgetType gtkWidgetType;
     989               0 :         if (GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, nsnull,
     990               0 :                                  nsnull)) {
     991                 :           moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top,
     992                 :                                     &aResult->right, &aResult->bottom, GetTextDirection(aFrame),
     993               0 :                                     IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML));
     994                 :         }
     995                 : 
     996                 :         gint horizontal_padding;
     997                 : 
     998               0 :         if (aWidgetType == NS_THEME_MENUITEM)
     999               0 :           moz_gtk_menuitem_get_horizontal_padding(&horizontal_padding);
    1000                 :         else
    1001               0 :           moz_gtk_checkmenuitem_get_horizontal_padding(&horizontal_padding);
    1002                 : 
    1003               0 :         aResult->left += horizontal_padding;
    1004               0 :         aResult->right += horizontal_padding;
    1005                 : 
    1006               0 :         return true;
    1007                 :       }
    1008                 :   }
    1009                 : 
    1010               0 :   return false;
    1011                 : }
    1012                 : 
    1013                 : bool
    1014               0 : nsNativeThemeGTK::GetWidgetOverflow(nsDeviceContext* aContext,
    1015                 :                                     nsIFrame* aFrame, PRUint8 aWidgetType,
    1016                 :                                     nsRect* aOverflowRect)
    1017                 : {
    1018               0 :   nsMargin m;
    1019                 :   PRInt32 p2a;
    1020               0 :   nsIntMargin extraSize;
    1021               0 :   if (!GetExtraSizeForWidget(aFrame, aWidgetType, &extraSize))
    1022               0 :     return false;
    1023                 : 
    1024               0 :   p2a = aContext->AppUnitsPerDevPixel();
    1025                 :   m = nsMargin(NSIntPixelsToAppUnits(extraSize.left, p2a),
    1026                 :                NSIntPixelsToAppUnits(extraSize.top, p2a),
    1027                 :                NSIntPixelsToAppUnits(extraSize.right, p2a),
    1028               0 :                NSIntPixelsToAppUnits(extraSize.bottom, p2a));
    1029                 : 
    1030               0 :   aOverflowRect->Inflate(m);
    1031               0 :   return true;
    1032                 : }
    1033                 : 
    1034                 : NS_IMETHODIMP
    1035               0 : nsNativeThemeGTK::GetMinimumWidgetSize(nsRenderingContext* aContext,
    1036                 :                                        nsIFrame* aFrame, PRUint8 aWidgetType,
    1037                 :                                        nsIntSize* aResult, bool* aIsOverridable)
    1038                 : {
    1039               0 :   aResult->width = aResult->height = 0;
    1040               0 :   *aIsOverridable = true;
    1041                 : 
    1042               0 :   switch (aWidgetType) {
    1043                 :     case NS_THEME_SCROLLBAR_BUTTON_UP:
    1044                 :     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
    1045                 :       {
    1046                 :         MozGtkScrollbarMetrics metrics;
    1047               0 :         moz_gtk_get_scrollbar_metrics(&metrics);
    1048                 : 
    1049               0 :         aResult->width = metrics.slider_width;
    1050               0 :         aResult->height = metrics.stepper_size;
    1051               0 :         *aIsOverridable = false;
    1052                 :       }
    1053               0 :       break;
    1054                 :     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
    1055                 :     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
    1056                 :       {
    1057                 :         MozGtkScrollbarMetrics metrics;
    1058               0 :         moz_gtk_get_scrollbar_metrics(&metrics);
    1059                 : 
    1060               0 :         aResult->width = metrics.stepper_size;
    1061               0 :         aResult->height = metrics.slider_width;
    1062               0 :         *aIsOverridable = false;
    1063                 :       }
    1064               0 :       break;
    1065                 :     case NS_THEME_SPLITTER:
    1066                 :     {
    1067                 :       gint metrics;
    1068               0 :       if (IsHorizontal(aFrame)) {
    1069               0 :         moz_gtk_splitter_get_metrics(GTK_ORIENTATION_HORIZONTAL, &metrics);
    1070               0 :         aResult->width = metrics;
    1071               0 :         aResult->height = 0;
    1072                 :       } else {
    1073               0 :         moz_gtk_splitter_get_metrics(GTK_ORIENTATION_VERTICAL, &metrics);
    1074               0 :         aResult->width = 0;
    1075               0 :         aResult->height = metrics;
    1076                 :       }
    1077               0 :       *aIsOverridable = false;
    1078                 :     }
    1079               0 :     break;
    1080                 :     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
    1081                 :     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
    1082                 :     {
    1083                 :       /* While we enforce a minimum size for the thumb, this is ignored
    1084                 :        * for the some scrollbars if buttons are hidden (bug 513006) because
    1085                 :        * the thumb isn't a direct child of the scrollbar, unlike the buttons
    1086                 :        * or track. So add a minimum size to the track as well to prevent a
    1087                 :        * 0-width scrollbar. */
    1088                 :       MozGtkScrollbarMetrics metrics;
    1089               0 :       moz_gtk_get_scrollbar_metrics(&metrics);
    1090                 : 
    1091               0 :       if (aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL)
    1092               0 :         aResult->width = metrics.slider_width;
    1093                 :       else
    1094               0 :         aResult->height = metrics.slider_width;
    1095                 : 
    1096               0 :       *aIsOverridable = false;
    1097                 :     }
    1098               0 :     break;
    1099                 :     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
    1100                 :     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
    1101                 :       {
    1102                 :         MozGtkScrollbarMetrics metrics;
    1103               0 :         moz_gtk_get_scrollbar_metrics(&metrics);
    1104                 : 
    1105               0 :         nsRect rect = aFrame->GetParent()->GetRect();
    1106                 :         PRInt32 p2a = aFrame->PresContext()->DeviceContext()->
    1107               0 :                         AppUnitsPerDevPixel();
    1108               0 :         nsMargin margin;
    1109                 : 
    1110                 :         /* Get the available space, if that is smaller then the minimum size,
    1111                 :          * adjust the mininum size to fit into it.
    1112                 :          * Setting aIsOverridable to true has no effect for thumbs. */
    1113               0 :         aFrame->GetMargin(margin);
    1114               0 :         rect.Deflate(margin);
    1115               0 :         aFrame->GetParent()->GetBorderAndPadding(margin);
    1116               0 :         rect.Deflate(margin);
    1117                 : 
    1118               0 :         if (aWidgetType == NS_THEME_SCROLLBAR_THUMB_VERTICAL) {
    1119               0 :           aResult->width = metrics.slider_width;
    1120               0 :           aResult->height = NS_MIN(NSAppUnitsToIntPixels(rect.height, p2a),
    1121               0 :                                    metrics.min_slider_size);
    1122                 :         } else {
    1123               0 :           aResult->height = metrics.slider_width;
    1124               0 :           aResult->width = NS_MIN(NSAppUnitsToIntPixels(rect.width, p2a),
    1125               0 :                                   metrics.min_slider_size);
    1126                 :         }
    1127                 : 
    1128               0 :         *aIsOverridable = false;
    1129                 :       }
    1130               0 :       break;
    1131                 :     case NS_THEME_SCALE_THUMB_HORIZONTAL:
    1132                 :     case NS_THEME_SCALE_THUMB_VERTICAL:
    1133                 :       {
    1134                 :         gint thumb_length, thumb_height;
    1135                 : 
    1136               0 :         if (aWidgetType == NS_THEME_SCALE_THUMB_VERTICAL) {
    1137               0 :           moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_length, &thumb_height);
    1138               0 :           aResult->width = thumb_height;
    1139               0 :           aResult->height = thumb_length;
    1140                 :         } else {
    1141               0 :           moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL, &thumb_length, &thumb_height);
    1142               0 :           aResult->width = thumb_length;
    1143               0 :           aResult->height = thumb_height;
    1144                 :         }
    1145                 : 
    1146               0 :         *aIsOverridable = false;
    1147                 :       }
    1148               0 :       break;
    1149                 :     case NS_THEME_TAB_SCROLLARROW_BACK:
    1150                 :     case NS_THEME_TAB_SCROLLARROW_FORWARD:
    1151                 :       {
    1152               0 :         moz_gtk_get_tab_scroll_arrow_size(&aResult->width, &aResult->height);
    1153               0 :         *aIsOverridable = false;
    1154                 :       }
    1155               0 :       break;
    1156                 :   case NS_THEME_DROPDOWN_BUTTON:
    1157                 :     {
    1158                 :       moz_gtk_get_combo_box_entry_button_size(&aResult->width,
    1159               0 :                                               &aResult->height);
    1160               0 :       *aIsOverridable = false;
    1161                 :     }
    1162               0 :     break;
    1163                 :   case NS_THEME_MENUSEPARATOR:
    1164                 :     {
    1165                 :       gint separator_height;
    1166                 : 
    1167               0 :       moz_gtk_get_menu_separator_height(&separator_height);
    1168               0 :       aResult->height = separator_height;
    1169                 :     
    1170               0 :       *aIsOverridable = false;
    1171                 :     }
    1172               0 :     break;
    1173                 :   case NS_THEME_CHECKBOX:
    1174                 :   case NS_THEME_RADIO:
    1175                 :     {
    1176                 :       gint indicator_size, indicator_spacing;
    1177                 : 
    1178               0 :       if (aWidgetType == NS_THEME_CHECKBOX) {
    1179               0 :         moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing);
    1180                 :       } else {
    1181               0 :         moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing);
    1182                 :       }
    1183                 : 
    1184                 :       // Include space for the indicator and the padding around it.
    1185               0 :       aResult->width = indicator_size;
    1186               0 :       aResult->height = indicator_size;
    1187               0 :       *aIsOverridable = false;
    1188                 :     }
    1189               0 :     break;
    1190                 :   case NS_THEME_TOOLBAR_BUTTON_DROPDOWN:
    1191                 :   case NS_THEME_BUTTON_ARROW_UP:
    1192                 :   case NS_THEME_BUTTON_ARROW_DOWN:
    1193                 :   case NS_THEME_BUTTON_ARROW_NEXT:
    1194                 :   case NS_THEME_BUTTON_ARROW_PREVIOUS:
    1195                 :     {
    1196               0 :         moz_gtk_get_arrow_size(&aResult->width, &aResult->height);
    1197               0 :         *aIsOverridable = false;
    1198                 :     }
    1199               0 :     break;
    1200                 :   case NS_THEME_CHECKBOX_CONTAINER:
    1201                 :   case NS_THEME_RADIO_CONTAINER:
    1202                 :   case NS_THEME_CHECKBOX_LABEL:
    1203                 :   case NS_THEME_RADIO_LABEL:
    1204                 :   case NS_THEME_BUTTON:
    1205                 :   case NS_THEME_DROPDOWN:
    1206                 :   case NS_THEME_TOOLBAR_BUTTON:
    1207                 :   case NS_THEME_TREEVIEW_HEADER_CELL:
    1208                 :     {
    1209                 :       // Just include our border, and let the box code augment the size.
    1210               0 :       nsIntMargin border;
    1211                 :       nsNativeThemeGTK::GetWidgetBorder(aContext->DeviceContext(),
    1212               0 :                                         aFrame, aWidgetType, &border);
    1213               0 :       aResult->width = border.left + border.right;
    1214               0 :       aResult->height = border.top + border.bottom;
    1215                 :     }
    1216               0 :     break;
    1217                 :   case NS_THEME_TOOLBAR_SEPARATOR:
    1218                 :     {
    1219                 :       gint separator_width;
    1220                 :     
    1221               0 :       moz_gtk_get_toolbar_separator_width(&separator_width);
    1222                 :     
    1223               0 :       aResult->width = separator_width;
    1224                 :     }
    1225               0 :     break;
    1226                 :   case NS_THEME_SPINNER:
    1227                 :     // hard code these sizes
    1228               0 :     aResult->width = 14;
    1229               0 :     aResult->height = 26;
    1230               0 :     break;
    1231                 :   case NS_THEME_TREEVIEW_HEADER_SORTARROW:
    1232                 :   case NS_THEME_SPINNER_UP_BUTTON:
    1233                 :   case NS_THEME_SPINNER_DOWN_BUTTON:
    1234                 :     // hard code these sizes
    1235               0 :     aResult->width = 14;
    1236               0 :     aResult->height = 13;
    1237               0 :     break;
    1238                 :   case NS_THEME_RESIZER:
    1239                 :     // same as Windows to make our lives easier
    1240               0 :     aResult->width = aResult->height = 15;
    1241               0 :     *aIsOverridable = false;
    1242               0 :     break;
    1243                 :   case NS_THEME_TREEVIEW_TWISTY:
    1244                 :   case NS_THEME_TREEVIEW_TWISTY_OPEN:
    1245                 :     {
    1246                 :       gint expander_size;
    1247                 : 
    1248               0 :       moz_gtk_get_treeview_expander_size(&expander_size);
    1249               0 :       aResult->width = aResult->height = expander_size;
    1250               0 :       *aIsOverridable = false;
    1251                 :     }
    1252               0 :     break;
    1253                 :   }
    1254               0 :   return NS_OK;
    1255                 : }
    1256                 : 
    1257                 : NS_IMETHODIMP
    1258               0 : nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType, 
    1259                 :                                      nsIAtom* aAttribute, bool* aShouldRepaint)
    1260                 : {
    1261                 :   // Some widget types just never change state.
    1262               0 :   if (aWidgetType == NS_THEME_TOOLBOX ||
    1263                 :       aWidgetType == NS_THEME_TOOLBAR ||
    1264                 :       aWidgetType == NS_THEME_STATUSBAR ||
    1265                 :       aWidgetType == NS_THEME_STATUSBAR_PANEL ||
    1266                 :       aWidgetType == NS_THEME_STATUSBAR_RESIZER_PANEL ||
    1267                 :       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
    1268                 :       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
    1269                 :       aWidgetType == NS_THEME_PROGRESSBAR ||
    1270                 :       aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL ||
    1271                 :       aWidgetType == NS_THEME_MENUBAR ||
    1272                 :       aWidgetType == NS_THEME_MENUPOPUP ||
    1273                 :       aWidgetType == NS_THEME_TOOLTIP ||
    1274                 :       aWidgetType == NS_THEME_MENUSEPARATOR ||
    1275                 :       aWidgetType == NS_THEME_WINDOW ||
    1276                 :       aWidgetType == NS_THEME_DIALOG) {
    1277               0 :     *aShouldRepaint = false;
    1278               0 :     return NS_OK;
    1279                 :   }
    1280                 : 
    1281               0 :   if ((aWidgetType == NS_THEME_SCROLLBAR_BUTTON_UP ||
    1282                 :        aWidgetType == NS_THEME_SCROLLBAR_BUTTON_DOWN ||
    1283                 :        aWidgetType == NS_THEME_SCROLLBAR_BUTTON_LEFT ||
    1284                 :        aWidgetType == NS_THEME_SCROLLBAR_BUTTON_RIGHT) &&
    1285                 :       (aAttribute == nsGkAtoms::curpos ||
    1286                 :        aAttribute == nsGkAtoms::maxpos)) {
    1287               0 :     *aShouldRepaint = true;
    1288               0 :     return NS_OK;
    1289                 :   }
    1290                 : 
    1291                 :   // XXXdwh Not sure what can really be done here.  Can at least guess for
    1292                 :   // specific widgets that they're highly unlikely to have certain states.
    1293                 :   // For example, a toolbar doesn't care about any states.
    1294               0 :   if (!aAttribute) {
    1295                 :     // Hover/focus/active changed.  Always repaint.
    1296               0 :     *aShouldRepaint = true;
    1297                 :   }
    1298                 :   else {
    1299                 :     // Check the attribute to see if it's relevant.  
    1300                 :     // disabled, checked, dlgtype, default, etc.
    1301               0 :     *aShouldRepaint = false;
    1302               0 :     if (aAttribute == nsGkAtoms::disabled ||
    1303                 :         aAttribute == nsGkAtoms::checked ||
    1304                 :         aAttribute == nsGkAtoms::selected ||
    1305                 :         aAttribute == nsGkAtoms::focused ||
    1306                 :         aAttribute == nsGkAtoms::readonly ||
    1307                 :         aAttribute == nsGkAtoms::_default ||
    1308                 :         aAttribute == nsGkAtoms::menuactive ||
    1309                 :         aAttribute == nsGkAtoms::open ||
    1310                 :         aAttribute == nsGkAtoms::parentfocused)
    1311               0 :       *aShouldRepaint = true;
    1312                 :   }
    1313                 : 
    1314               0 :   return NS_OK;
    1315                 : }
    1316                 : 
    1317                 : NS_IMETHODIMP
    1318               0 : nsNativeThemeGTK::ThemeChanged()
    1319                 : {
    1320               0 :   memset(mDisabledWidgetTypes, 0, sizeof(mDisabledWidgetTypes));
    1321               0 :   return NS_OK;
    1322                 : }
    1323                 : 
    1324                 : NS_IMETHODIMP_(bool)
    1325               0 : nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
    1326                 :                                       nsIFrame* aFrame,
    1327                 :                                       PRUint8 aWidgetType)
    1328                 : {
    1329               0 :   if (IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType))
    1330               0 :     return false;
    1331                 : 
    1332               0 :   switch (aWidgetType) {
    1333                 :   case NS_THEME_BUTTON:
    1334                 :   case NS_THEME_BUTTON_FOCUS:
    1335                 :   case NS_THEME_RADIO:
    1336                 :   case NS_THEME_CHECKBOX:
    1337                 :   case NS_THEME_TOOLBOX: // N/A
    1338                 :   case NS_THEME_TOOLBAR:
    1339                 :   case NS_THEME_TOOLBAR_BUTTON:
    1340                 :   case NS_THEME_TOOLBAR_DUAL_BUTTON: // so we can override the border with 0
    1341                 :   case NS_THEME_TOOLBAR_BUTTON_DROPDOWN:
    1342                 :   case NS_THEME_BUTTON_ARROW_UP:
    1343                 :   case NS_THEME_BUTTON_ARROW_DOWN:
    1344                 :   case NS_THEME_BUTTON_ARROW_NEXT:
    1345                 :   case NS_THEME_BUTTON_ARROW_PREVIOUS:
    1346                 :   case NS_THEME_TOOLBAR_SEPARATOR:
    1347                 :   case NS_THEME_TOOLBAR_GRIPPER:
    1348                 :   case NS_THEME_STATUSBAR:
    1349                 :   case NS_THEME_STATUSBAR_PANEL:
    1350                 :   case NS_THEME_STATUSBAR_RESIZER_PANEL:
    1351                 :   case NS_THEME_RESIZER:
    1352                 :   case NS_THEME_LISTBOX:
    1353                 :     // case NS_THEME_LISTBOX_LISTITEM:
    1354                 :   case NS_THEME_TREEVIEW:
    1355                 :     // case NS_THEME_TREEVIEW_TREEITEM:
    1356                 :   case NS_THEME_TREEVIEW_TWISTY:
    1357                 :     // case NS_THEME_TREEVIEW_LINE:
    1358                 :     // case NS_THEME_TREEVIEW_HEADER:
    1359                 :   case NS_THEME_TREEVIEW_HEADER_CELL:
    1360                 :   case NS_THEME_TREEVIEW_HEADER_SORTARROW:
    1361                 :   case NS_THEME_TREEVIEW_TWISTY_OPEN:
    1362                 :     case NS_THEME_PROGRESSBAR:
    1363                 :     case NS_THEME_PROGRESSBAR_CHUNK:
    1364                 :     case NS_THEME_PROGRESSBAR_VERTICAL:
    1365                 :     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
    1366                 :     case NS_THEME_TAB:
    1367                 :     // case NS_THEME_TAB_PANEL:
    1368                 :     case NS_THEME_TAB_PANELS:
    1369                 :     case NS_THEME_TAB_SCROLLARROW_BACK:
    1370                 :     case NS_THEME_TAB_SCROLLARROW_FORWARD:
    1371                 :   case NS_THEME_TOOLTIP:
    1372                 :   case NS_THEME_SPINNER:
    1373                 :   case NS_THEME_SPINNER_UP_BUTTON:
    1374                 :   case NS_THEME_SPINNER_DOWN_BUTTON:
    1375                 :   case NS_THEME_SPINNER_TEXTFIELD:
    1376                 :     // case NS_THEME_SCROLLBAR:  (n/a for gtk)
    1377                 :     // case NS_THEME_SCROLLBAR_SMALL: (n/a for gtk)
    1378                 :   case NS_THEME_SCROLLBAR_BUTTON_UP:
    1379                 :   case NS_THEME_SCROLLBAR_BUTTON_DOWN:
    1380                 :   case NS_THEME_SCROLLBAR_BUTTON_LEFT:
    1381                 :   case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
    1382                 :   case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
    1383                 :   case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
    1384                 :   case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
    1385                 :   case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
    1386                 :   case NS_THEME_TEXTFIELD:
    1387                 :   case NS_THEME_TEXTFIELD_MULTILINE:
    1388                 :   case NS_THEME_TEXTFIELD_CARET:
    1389                 :   case NS_THEME_DROPDOWN_TEXTFIELD:
    1390                 :   case NS_THEME_SCALE_HORIZONTAL:
    1391                 :   case NS_THEME_SCALE_THUMB_HORIZONTAL:
    1392                 :   case NS_THEME_SCALE_VERTICAL:
    1393                 :   case NS_THEME_SCALE_THUMB_VERTICAL:
    1394                 :     // case NS_THEME_SCALE_THUMB_START:
    1395                 :     // case NS_THEME_SCALE_THUMB_END:
    1396                 :     // case NS_THEME_SCALE_TICK:
    1397                 :   case NS_THEME_CHECKBOX_CONTAINER:
    1398                 :   case NS_THEME_RADIO_CONTAINER:
    1399                 :   case NS_THEME_CHECKBOX_LABEL:
    1400                 :   case NS_THEME_RADIO_LABEL:
    1401                 :   case NS_THEME_MENUBAR:
    1402                 :   case NS_THEME_MENUPOPUP:
    1403                 :   case NS_THEME_MENUITEM:
    1404                 :   case NS_THEME_MENUARROW:
    1405                 :   case NS_THEME_MENUSEPARATOR:
    1406                 :   case NS_THEME_CHECKMENUITEM:
    1407                 :   case NS_THEME_RADIOMENUITEM:
    1408                 :   case NS_THEME_SPLITTER:
    1409                 :   case NS_THEME_WINDOW:
    1410                 :   case NS_THEME_DIALOG:
    1411                 :   case NS_THEME_DROPDOWN:
    1412                 :   case NS_THEME_DROPDOWN_TEXT:
    1413               0 :     return !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
    1414                 : 
    1415                 :   case NS_THEME_DROPDOWN_BUTTON:
    1416                 :     // "Native" dropdown buttons cause padding and margin problems, but only
    1417                 :     // in HTML so allow them in XUL.
    1418               0 :     return (!aFrame || IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
    1419               0 :            !IsWidgetStyled(aPresContext, aFrame, aWidgetType);
    1420                 : 
    1421                 :   }
    1422                 : 
    1423               0 :   return false;
    1424                 : }
    1425                 : 
    1426                 : NS_IMETHODIMP_(bool)
    1427               0 : nsNativeThemeGTK::WidgetIsContainer(PRUint8 aWidgetType)
    1428                 : {
    1429                 :   // XXXdwh At some point flesh all of this out.
    1430               0 :   if (aWidgetType == NS_THEME_DROPDOWN_BUTTON ||
    1431                 :       aWidgetType == NS_THEME_RADIO ||
    1432                 :       aWidgetType == NS_THEME_CHECKBOX ||
    1433                 :       aWidgetType == NS_THEME_TAB_SCROLLARROW_BACK ||
    1434                 :       aWidgetType == NS_THEME_TAB_SCROLLARROW_FORWARD ||
    1435                 :       aWidgetType == NS_THEME_BUTTON_ARROW_UP ||
    1436                 :       aWidgetType == NS_THEME_BUTTON_ARROW_DOWN ||
    1437                 :       aWidgetType == NS_THEME_BUTTON_ARROW_NEXT ||
    1438                 :       aWidgetType == NS_THEME_BUTTON_ARROW_PREVIOUS)
    1439               0 :     return false;
    1440               0 :   return true;
    1441                 : }
    1442                 : 
    1443                 : bool
    1444               0 : nsNativeThemeGTK::ThemeDrawsFocusForWidget(nsPresContext* aPresContext, nsIFrame* aFrame, PRUint8 aWidgetType)
    1445                 : {
    1446               0 :    if (aWidgetType == NS_THEME_DROPDOWN ||
    1447                 :       aWidgetType == NS_THEME_BUTTON || 
    1448                 :       aWidgetType == NS_THEME_TREEVIEW_HEADER_CELL)
    1449               0 :     return true;
    1450                 :   
    1451               0 :   return false;
    1452                 : }
    1453                 : 
    1454                 : bool
    1455               0 : nsNativeThemeGTK::ThemeNeedsComboboxDropmarker()
    1456                 : {
    1457               0 :   return false;
    1458                 : }
    1459                 : 
    1460                 : nsITheme::Transparency
    1461               0 : nsNativeThemeGTK::GetWidgetTransparency(nsIFrame* aFrame, PRUint8 aWidgetType)
    1462                 : {
    1463               0 :   switch (aWidgetType) {
    1464                 :   // These widgets always draw a default background.
    1465                 :   case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
    1466                 :   case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
    1467                 :   case NS_THEME_SCALE_HORIZONTAL:
    1468                 :   case NS_THEME_SCALE_VERTICAL:
    1469                 :   case NS_THEME_TOOLBAR:
    1470                 :   case NS_THEME_MENUBAR:
    1471                 :   case NS_THEME_MENUPOPUP:
    1472                 :   case NS_THEME_WINDOW:
    1473                 :   case NS_THEME_DIALOG:
    1474                 :   // Tooltips use gtk_paint_flat_box().
    1475                 :   case NS_THEME_TOOLTIP:
    1476               0 :     return eOpaque;
    1477                 :   }
    1478                 : 
    1479               0 :   return eUnknownTransparency;
    1480                 : }

Generated by: LCOV version 1.7