Back to index

lightning-sunbird  0.9+nobinonly
nsNativeThemeWin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * David Hyatt (hyatt@netscape.com).
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Tim Hill (tim@prismelite.com)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include <windows.h>
00040 #include "nsNativeThemeWin.h"
00041 #include "nsRenderingContextWin.h"
00042 #include "nsDeviceContextWin.h"
00043 #include "nsRect.h"
00044 #include "nsSize.h"
00045 #include "nsTransform2D.h"
00046 #include "nsThemeConstants.h"
00047 #include "nsIPresShell.h"
00048 #include "nsPresContext.h"
00049 #include "nsIContent.h"
00050 #include "nsIDocument.h"
00051 #include "nsIFrame.h"
00052 #include "nsIEventStateManager.h"
00053 #include "nsINameSpaceManager.h"
00054 #include "nsILookAndFeel.h"
00055 #include "nsIDOMHTMLInputElement.h"
00056 #include "nsIMenuFrame.h"
00057 #include "nsUnicharUtils.h"
00058 #include <malloc.h>
00059 
00060 /* 
00061  * The following constants are used to determine how a widget is drawn using
00062  * Windows' Theme API. For more information on theme parts and states see
00063  * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
00064  */
00065 #define THEME_COLOR 204
00066 #define THEME_FONT  210
00067 
00068 // Generic state constants
00069 #define TS_NORMAL    1
00070 #define TS_HOVER     2
00071 #define TS_ACTIVE    3
00072 #define TS_DISABLED  4
00073 #define TS_FOCUSED   5
00074 
00075 // Toolbarbutton constants
00076 #define TB_CHECKED       5
00077 #define TB_HOVER_CHECKED 6
00078 
00079 // Button constants
00080 #define BP_BUTTON    1
00081 #define BP_RADIO     2
00082 #define BP_CHECKBOX  3
00083 
00084 // Textfield constants
00085 #define TFP_TEXTFIELD 1
00086 #define TFS_READONLY  6
00087 
00088 // Treeview/listbox constants
00089 #define TREEVIEW_BODY 1
00090 
00091 // Scrollbar constants
00092 #define SP_BUTTON          1
00093 #define SP_THUMBHOR        2
00094 #define SP_THUMBVERT       3
00095 #define SP_TRACKSTARTHOR   4
00096 #define SP_TRACKENDHOR     5
00097 #define SP_TRACKSTARTVERT  6
00098 #define SP_TRACKENDVERT    7
00099 #define SP_GRIPPERHOR      8
00100 #define SP_GRIPPERVERT     9
00101 
00102 // Progress bar constants
00103 #define PP_BAR             1
00104 #define PP_BARVERT         2
00105 #define PP_CHUNK           3
00106 #define PP_CHUNKVERT       4
00107 
00108 // Tab constants
00109 #define TABP_TAB             4
00110 #define TABP_TAB_SELECTED    5
00111 #define TABP_PANELS          9
00112 #define TABP_PANEL           10
00113 
00114 // Tooltip constants
00115 #define TTP_STANDARD         1
00116 
00117 // Dropdown constants
00118 #define CBP_DROPMARKER       1
00119 
00120 NS_IMPL_ISUPPORTS1(nsNativeThemeWin, nsITheme)
00121 
00122 typedef HANDLE (WINAPI*OpenThemeDataPtr)(HWND hwnd, LPCWSTR pszClassList);
00123 typedef HRESULT (WINAPI*CloseThemeDataPtr)(HANDLE hTheme);
00124 typedef HRESULT (WINAPI*DrawThemeBackgroundPtr)(HANDLE hTheme, HDC hdc, int iPartId, 
00125                                           int iStateId, const RECT *pRect,
00126                                           const RECT* pClipRect);
00127 typedef HRESULT (WINAPI*GetThemeContentRectPtr)(HANDLE hTheme, HDC hdc, int iPartId,
00128                                           int iStateId, const RECT* pRect,
00129                                           RECT* pContentRect);
00130 typedef HRESULT (WINAPI*GetThemePartSizePtr)(HANDLE hTheme, HDC hdc, int iPartId,
00131                                        int iStateId, RECT* prc, int ts,
00132                                        SIZE* psz);
00133 typedef HRESULT (WINAPI*GetThemeSysFontPtr)(HANDLE hTheme, int iFontId, OUT LOGFONT* pFont);
00134 typedef HRESULT (WINAPI*GetThemeColorPtr)(HANDLE hTheme, HDC hdc, int iPartId,
00135                                    int iStateId, int iPropId, OUT COLORREF* pFont);
00136 
00137 static OpenThemeDataPtr openTheme = NULL;
00138 static CloseThemeDataPtr closeTheme = NULL;
00139 static DrawThemeBackgroundPtr drawThemeBG = NULL;
00140 static GetThemeContentRectPtr getThemeContentRect = NULL;
00141 static GetThemePartSizePtr getThemePartSize = NULL;
00142 static GetThemeSysFontPtr getThemeSysFont = NULL;
00143 static GetThemeColorPtr getThemeColor = NULL;
00144 
00145 static const char kThemeLibraryName[] = "uxtheme.dll";
00146 
00147 nsNativeThemeWin::nsNativeThemeWin() {
00148   mThemeDLL = NULL;
00149   mButtonTheme = NULL;
00150   mTextFieldTheme = NULL;
00151   mTooltipTheme = NULL;
00152   mToolbarTheme = NULL;
00153   mRebarTheme = NULL;
00154   mProgressTheme = NULL;
00155   mScrollbarTheme = NULL;
00156   mStatusbarTheme = NULL;
00157   mTabTheme = NULL;
00158   mTreeViewTheme = NULL;
00159   mComboBoxTheme = NULL;
00160   mHeaderTheme = NULL;
00161 
00162   mThemeDLL = ::LoadLibrary(kThemeLibraryName);
00163   if (mThemeDLL) {
00164     openTheme = (OpenThemeDataPtr)GetProcAddress(mThemeDLL, "OpenThemeData");
00165     closeTheme = (CloseThemeDataPtr)GetProcAddress(mThemeDLL, "CloseThemeData");
00166     drawThemeBG = (DrawThemeBackgroundPtr)GetProcAddress(mThemeDLL, "DrawThemeBackground");
00167     getThemeContentRect = (GetThemeContentRectPtr)GetProcAddress(mThemeDLL, "GetThemeBackgroundContentRect");
00168     getThemePartSize = (GetThemePartSizePtr)GetProcAddress(mThemeDLL, "GetThemePartSize");
00169     getThemeSysFont = (GetThemeSysFontPtr)GetProcAddress(mThemeDLL, "GetThemeSysFont");
00170     getThemeColor = (GetThemeColorPtr)GetProcAddress(mThemeDLL, "GetThemeColor");
00171   }
00172 
00173   mInputAtom = do_GetAtom("input");
00174   mInputCheckedAtom = do_GetAtom("_moz-input-checked");
00175   mTypeAtom = do_GetAtom("type");
00176 
00177   // If there is a relevant change in forms.css for windows platform,
00178   // static widget style variables (e.g. sButtonBorderSize) should be 
00179   // reinitialized here.
00180 }
00181 
00182 nsNativeThemeWin::~nsNativeThemeWin() {
00183   if (!mThemeDLL)
00184     return;
00185 
00186   CloseData();
00187   
00188   if (mThemeDLL)
00189     ::FreeLibrary(mThemeDLL);
00190 }
00191 
00192 static void GetNativeRect(const nsRect& aSrc, RECT& aDst) 
00193 {
00194   aDst.top = aSrc.y;
00195   aDst.bottom = aSrc.y + aSrc.height;
00196   aDst.left = aSrc.x;
00197   aDst.right = aSrc.x + aSrc.width;
00198 }
00199 
00200 HANDLE
00201 nsNativeThemeWin::GetTheme(PRUint8 aWidgetType)
00202 { 
00203   if (!mThemeDLL)
00204     return NULL;
00205 
00206   switch (aWidgetType) {
00207     case NS_THEME_BUTTON:
00208     case NS_THEME_RADIO:
00209     case NS_THEME_CHECKBOX: {
00210       if (!mButtonTheme)
00211         mButtonTheme = openTheme(NULL, L"Button");
00212       return mButtonTheme;
00213     }
00214     case NS_THEME_TEXTFIELD:
00215     case NS_THEME_DROPDOWN: {
00216       if (!mTextFieldTheme)
00217         mTextFieldTheme = openTheme(NULL, L"Edit");
00218       return mTextFieldTheme;
00219     }
00220     case NS_THEME_TOOLTIP: {
00221       if (!mTooltipTheme)
00222         mTooltipTheme = openTheme(NULL, L"Tooltip");
00223       return mTooltipTheme;
00224     }
00225     case NS_THEME_TOOLBOX: {
00226       if (!mRebarTheme)
00227         mRebarTheme = openTheme(NULL, L"Rebar");
00228       return mRebarTheme;
00229     }
00230     case NS_THEME_TOOLBAR:
00231     case NS_THEME_TOOLBAR_BUTTON: {
00232       if (!mToolbarTheme)
00233         mToolbarTheme = openTheme(NULL, L"Toolbar");
00234       return mToolbarTheme;
00235     }
00236     case NS_THEME_PROGRESSBAR:
00237     case NS_THEME_PROGRESSBAR_VERTICAL:
00238     case NS_THEME_PROGRESSBAR_CHUNK:
00239     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL: {
00240       if (!mProgressTheme)
00241         mProgressTheme = openTheme(NULL, L"Progress");
00242       return mProgressTheme;
00243     }
00244     case NS_THEME_TAB:
00245     case NS_THEME_TAB_LEFT_EDGE:
00246     case NS_THEME_TAB_RIGHT_EDGE:
00247     case NS_THEME_TAB_PANEL:
00248     case NS_THEME_TAB_PANELS: {
00249       if (!mTabTheme)
00250         mTabTheme = openTheme(NULL, L"Tab");
00251       return mTabTheme;
00252     }
00253     case NS_THEME_SCROLLBAR:
00254     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
00255     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
00256     case NS_THEME_SCROLLBAR_BUTTON_UP:
00257     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
00258     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
00259     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
00260     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
00261     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
00262     case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
00263     case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL:
00264     {
00265       if (!mScrollbarTheme)
00266         mScrollbarTheme = openTheme(NULL, L"Scrollbar");
00267       return mScrollbarTheme;
00268     }
00269     case NS_THEME_STATUSBAR:
00270     case NS_THEME_STATUSBAR_PANEL:
00271     case NS_THEME_STATUSBAR_RESIZER_PANEL:
00272     case NS_THEME_RESIZER:
00273     {
00274       if (!mStatusbarTheme)
00275         mStatusbarTheme = openTheme(NULL, L"Status");
00276       return mStatusbarTheme;
00277     }
00278     case NS_THEME_DROPDOWN_BUTTON: {
00279       if (!mComboBoxTheme)
00280         mComboBoxTheme = openTheme(NULL, L"Combobox");
00281       return mComboBoxTheme;
00282     }
00283     case NS_THEME_TREEVIEW_HEADER_CELL:
00284     case NS_THEME_TREEVIEW_HEADER_SORTARROW: {
00285       if (!mHeaderTheme)
00286         mHeaderTheme = openTheme(NULL, L"Header");
00287       return mHeaderTheme;
00288     }
00289     case NS_THEME_LISTBOX:
00290     case NS_THEME_LISTBOX_LISTITEM:
00291     case NS_THEME_TREEVIEW:
00292     case NS_THEME_TREEVIEW_TWISTY_OPEN:
00293     case NS_THEME_TREEVIEW_TREEITEM: {
00294       if (!mTreeViewTheme)
00295         mTreeViewTheme = openTheme(NULL, L"Listview");
00296       return mTreeViewTheme;
00297     }
00298   }
00299   return NULL;
00300 }
00301 
00302 nsresult 
00303 nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType, 
00304                                        PRInt32& aPart, PRInt32& aState)
00305 {
00306   switch (aWidgetType) {
00307     case NS_THEME_BUTTON: {
00308       aPart = BP_BUTTON;
00309       if (!aFrame) {
00310         aState = TS_NORMAL;
00311         return NS_OK;
00312       }
00313 
00314       if (IsDisabled(aFrame)) {
00315         aState = TS_DISABLED;
00316         return NS_OK;
00317       }
00318       PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00319       if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00320         aState = TS_ACTIVE;
00321       else if (eventState & NS_EVENT_STATE_FOCUS)
00322         aState = TS_FOCUSED;
00323       else if (eventState & NS_EVENT_STATE_HOVER)
00324         aState = TS_HOVER;
00325       else 
00326         aState = TS_NORMAL;
00327       
00328       // Check for default dialog buttons.  These buttons should always look
00329       // focused.
00330       if (aState == TS_NORMAL && IsDefaultButton(aFrame))
00331         aState = TS_FOCUSED;
00332       return NS_OK;
00333     }
00334     case NS_THEME_CHECKBOX:
00335     case NS_THEME_RADIO: {
00336       aPart = (aWidgetType == NS_THEME_CHECKBOX) ? BP_CHECKBOX : BP_RADIO; 
00337 
00338       // XXXdwh This check will need to be more complicated, since HTML radio groups
00339       // use checked, but XUL radio groups use selected.  There will need to be an
00340       // IsContentOfType test for HTML vs. XUL here.
00341       nsIAtom* atom = (aWidgetType == NS_THEME_CHECKBOX) ? mCheckedAtom : mSelectedAtom;
00342 
00343       PRBool isHTML = PR_FALSE;
00344       PRBool isHTMLChecked = PR_FALSE;
00345       PRBool isXULCheckboxRadio = PR_FALSE;
00346       
00347       if (!aFrame)
00348         aState = TS_NORMAL;
00349       else {
00350         // For XUL checkboxes and radio buttons, the state of the parent
00351         // determines our state.
00352         nsIContent* content = aFrame->GetContent();
00353         PRBool isXULCheckboxRadio = content->IsContentOfType(nsIContent::eXUL);
00354         if (!isXULCheckboxRadio) {
00355           // Attempt a QI.
00356           nsCOMPtr<nsIDOMHTMLInputElement> inputElt(do_QueryInterface(content));
00357           if (inputElt) {
00358             inputElt->GetChecked(&isHTMLChecked);
00359             isHTML = PR_TRUE;
00360           }
00361         }
00362 
00363         if (IsDisabled(isXULCheckboxRadio ? aFrame->GetParent(): aFrame))
00364           aState = TS_DISABLED;
00365         else {
00366           PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00367           if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00368             aState = TS_ACTIVE;
00369           else if (eventState & NS_EVENT_STATE_HOVER)
00370             aState = TS_HOVER;
00371           else 
00372             aState = TS_NORMAL;
00373         }
00374       }
00375 
00376       if (isHTML) {
00377         if (isHTMLChecked)
00378           aState += 4;
00379       }
00380       else if (aWidgetType == NS_THEME_CHECKBOX ?
00381                IsChecked(aFrame) : IsSelected(aFrame))
00382         aState += 4; // 4 unchecked states, 4 checked states.
00383       return NS_OK;
00384     }
00385     case NS_THEME_TEXTFIELD:
00386     case NS_THEME_DROPDOWN: {
00387       aPart = TFP_TEXTFIELD;
00388       if (!aFrame) {
00389         aState = TS_NORMAL;
00390         return NS_OK;
00391       }
00392 
00393       if (IsDisabled(aFrame)) {
00394         aState = TS_DISABLED;
00395         return NS_OK;
00396       }
00397 
00398       if (IsReadOnly(aFrame)) {
00399         aState = TFS_READONLY;
00400         return NS_OK;
00401       }
00402 
00403       PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00404       if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00405         aState = TS_ACTIVE;
00406       else if (eventState & NS_EVENT_STATE_FOCUS)
00407         aState = TS_FOCUSED;
00408       else if (eventState & NS_EVENT_STATE_HOVER)
00409         aState = TS_HOVER;
00410       else 
00411         aState = TS_NORMAL;
00412       
00413       return NS_OK;
00414     }
00415     case NS_THEME_TOOLTIP: {
00416       aPart = TTP_STANDARD;
00417       aState = TS_NORMAL;
00418       return NS_OK;
00419     }
00420     case NS_THEME_PROGRESSBAR: {
00421       aPart = PP_BAR;
00422       aState = TS_NORMAL;
00423       return NS_OK;
00424     }
00425     case NS_THEME_PROGRESSBAR_CHUNK: {
00426       aPart = PP_CHUNK;
00427       aState = TS_NORMAL;
00428       return NS_OK;
00429     }
00430     case NS_THEME_PROGRESSBAR_VERTICAL: {
00431       aPart = PP_BARVERT;
00432       aState = TS_NORMAL;
00433       return NS_OK;
00434     }
00435     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL: {
00436       aPart = PP_CHUNKVERT;
00437       aState = TS_NORMAL;
00438       return NS_OK;
00439     }
00440     case NS_THEME_TOOLBAR_BUTTON: {
00441       aPart = BP_BUTTON;
00442       if (!aFrame) {
00443         aState = TS_NORMAL;
00444         return NS_OK;
00445       }
00446 
00447       if (IsDisabled(aFrame)) {
00448         aState = TS_DISABLED;
00449         return NS_OK;
00450       }
00451       PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00452       if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00453         aState = TS_ACTIVE;
00454       else if (eventState & NS_EVENT_STATE_HOVER) {
00455         if (IsCheckedButton(aFrame))
00456           aState = TB_HOVER_CHECKED;
00457         else
00458           aState = TS_HOVER;
00459       }
00460       else {
00461         if (IsCheckedButton(aFrame))
00462           aState = TB_CHECKED;
00463         else
00464           aState = TS_NORMAL;
00465       }
00466      
00467       return NS_OK;
00468     }
00469     case NS_THEME_SCROLLBAR_BUTTON_UP:
00470     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
00471     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
00472     case NS_THEME_SCROLLBAR_BUTTON_RIGHT: {
00473       aPart = SP_BUTTON;
00474       aState = (aWidgetType - NS_THEME_SCROLLBAR_BUTTON_UP)*4;
00475       if (!aFrame)
00476         aState += TS_NORMAL;
00477       else if (IsDisabled(aFrame))
00478         aState += TS_DISABLED;
00479       else {
00480         PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00481         if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00482           aState += TS_ACTIVE;
00483         else if (eventState & NS_EVENT_STATE_HOVER)
00484           aState += TS_HOVER;
00485         else
00486           aState += TS_NORMAL;
00487       }
00488       return NS_OK;
00489     }
00490     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
00491     case NS_THEME_SCROLLBAR_TRACK_VERTICAL: {
00492       aPart = (aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL) ?
00493               SP_TRACKSTARTHOR : SP_TRACKSTARTVERT;
00494       aState = TS_NORMAL;
00495       return NS_OK;
00496     }
00497     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
00498     case NS_THEME_SCROLLBAR_THUMB_VERTICAL: {
00499       aPart = (aWidgetType == NS_THEME_SCROLLBAR_THUMB_HORIZONTAL) ?
00500               SP_THUMBHOR : SP_THUMBVERT;
00501       if (!aFrame)
00502         aState = TS_NORMAL;
00503       else if (IsDisabled(aFrame))
00504         aState = TS_DISABLED;
00505       else {
00506         PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00507         if (eventState & NS_EVENT_STATE_ACTIVE) // Hover is not also a requirement for
00508                                                 // the thumb, since the drag is not canceled
00509                                                 // when you move outside the thumb.
00510           aState = TS_ACTIVE;
00511         else if (eventState & NS_EVENT_STATE_HOVER)
00512           aState = TS_HOVER;
00513         else 
00514           aState = TS_NORMAL;
00515       }
00516       return NS_OK;
00517     }
00518     case NS_THEME_SCROLLBAR_GRIPPER_VERTICAL:
00519     case NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL: {
00520       aPart = (aWidgetType == NS_THEME_SCROLLBAR_GRIPPER_HORIZONTAL) ?
00521               SP_GRIPPERHOR : SP_GRIPPERVERT;
00522       if (!aFrame)
00523         aState = TS_NORMAL;
00524       else if (IsDisabled(aFrame))
00525         aState = TS_DISABLED;
00526       else {
00527         // XXXdwh The gripper needs to get a hover attribute set on it, since it
00528         // never goes into :hover.
00529         PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00530         if (eventState & NS_EVENT_STATE_ACTIVE) // Hover is not also a requirement for
00531                                                 // the gripper, since the drag is not canceled
00532                                                 // when you move outside the gripper.
00533           aState = TS_ACTIVE;
00534         else if (eventState & NS_EVENT_STATE_HOVER)
00535           aState = TS_HOVER;
00536         else 
00537           aState = TS_NORMAL;
00538       }
00539       return NS_OK;
00540     }
00541     case NS_THEME_TOOLBOX:
00542     case NS_THEME_STATUSBAR:
00543     case NS_THEME_SCROLLBAR: {
00544       aPart = aState = 0;
00545       return NS_OK; // These have no part or state.
00546     }
00547     case NS_THEME_STATUSBAR_PANEL:
00548     case NS_THEME_STATUSBAR_RESIZER_PANEL:
00549     case NS_THEME_RESIZER: {
00550       aPart = (aWidgetType - NS_THEME_STATUSBAR_PANEL) + 1;
00551       aState = TS_NORMAL;
00552       return NS_OK;
00553     }
00554     case NS_THEME_TREEVIEW:
00555     case NS_THEME_LISTBOX: {
00556       aPart = TREEVIEW_BODY;
00557       aState = TS_NORMAL;
00558       return NS_OK;
00559     }
00560     case NS_THEME_TAB_PANELS: {
00561       aPart = TABP_PANELS;
00562       aState = TS_NORMAL;
00563       return NS_OK;
00564     }
00565     case NS_THEME_TAB_PANEL: {
00566       aPart = TABP_PANEL;
00567       aState = TS_NORMAL;
00568       return NS_OK;
00569     }
00570     case NS_THEME_TAB:
00571     case NS_THEME_TAB_LEFT_EDGE:
00572     case NS_THEME_TAB_RIGHT_EDGE: {
00573       aPart = TABP_TAB;
00574       if (!aFrame) {
00575         aState = TS_NORMAL;
00576         return NS_OK;
00577       }
00578       
00579       if (IsDisabled(aFrame)) {
00580         aState = TS_DISABLED;
00581         return NS_OK;
00582       }
00583 
00584       if (IsSelectedTab(aFrame)) {
00585         aPart = TABP_TAB_SELECTED;
00586         aState = TS_ACTIVE; // The selected tab is always "pressed".
00587       }
00588       else {
00589         PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00590         if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00591           aState = TS_ACTIVE;
00592         else if (eventState & NS_EVENT_STATE_FOCUS)
00593           aState = TS_FOCUSED;
00594         else if (eventState & NS_EVENT_STATE_HOVER)
00595           aState = TS_HOVER;
00596         else 
00597           aState = TS_NORMAL;
00598       }
00599       
00600       return NS_OK;
00601     }
00602     case NS_THEME_TREEVIEW_HEADER_SORTARROW: {
00603       // XXX Probably will never work due to a bug in the Luna theme.
00604       aPart = 4;
00605       aState = 1;
00606       return NS_OK;
00607     }
00608     case NS_THEME_TREEVIEW_HEADER_CELL: {
00609       aPart = 1;
00610       if (!aFrame) {
00611         aState = TS_NORMAL;
00612         return NS_OK;
00613       }
00614       
00615       PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00616       if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00617         aState = TS_ACTIVE;
00618       else if (eventState & NS_EVENT_STATE_FOCUS)
00619         aState = TS_FOCUSED;
00620       else if (eventState & NS_EVENT_STATE_HOVER)
00621         aState = TS_HOVER;
00622       else 
00623         aState = TS_NORMAL;
00624       
00625       return NS_OK;
00626     }
00627     case NS_THEME_DROPDOWN_BUTTON: {
00628       aPart = CBP_DROPMARKER;
00629 
00630       nsIContent* content = aFrame->GetContent();
00631 
00632       nsIFrame* parentFrame = aFrame->GetParent();
00633       nsCOMPtr<nsIMenuFrame> menuFrame(do_QueryInterface(parentFrame));
00634       if (menuFrame || (content && content->IsContentOfType(nsIContent::eHTML)) )
00635          // XUL menu lists and HTML selects get state from parent         
00636          aFrame = parentFrame;
00637 
00638       if (IsDisabled(aFrame))
00639         aState = TS_DISABLED;
00640       else {     
00641         PRInt32 eventState = GetContentState(aFrame, aWidgetType);
00642         if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
00643           aState = TS_ACTIVE;
00644         else if (eventState & NS_EVENT_STATE_HOVER)
00645           aState = TS_HOVER;
00646         else 
00647           aState = TS_NORMAL;
00648       }
00649 
00650       return NS_OK;
00651     }
00652   }
00653 
00654   aPart = 0;
00655   aState = 0;
00656   return NS_ERROR_FAILURE;
00657 }
00658 
00659 NS_IMETHODIMP
00660 nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext,
00661                                        nsIFrame* aFrame,
00662                                        PRUint8 aWidgetType,
00663                                        const nsRect& aRect,
00664                                        const nsRect& aClipRect)
00665 {
00666   HANDLE theme = GetTheme(aWidgetType);
00667   if (!theme)
00668     return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aClipRect); 
00669 
00670   if (!drawThemeBG)
00671     return NS_ERROR_FAILURE;    
00672 
00673   PRInt32 part, state;
00674   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
00675   if (NS_FAILED(rv))
00676     return rv;
00677 
00678   nsTransform2D* transformMatrix;
00679   aContext->GetCurrentTransform(transformMatrix);
00680   RECT widgetRect;
00681   RECT clipRect;
00682        nsRect tr(aRect);
00683   nsRect cr(aClipRect);
00684        transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
00685   GetNativeRect(tr, widgetRect);
00686   transformMatrix->TransformCoord(&cr.x,&cr.y,&cr.width,&cr.height);
00687   GetNativeRect(cr, clipRect);
00688   HDC hdc = NS_STATIC_CAST(nsRenderingContextWin*, aContext)->mDC;
00689   if (!hdc)
00690     return NS_ERROR_FAILURE;
00691   
00692   // For left edge and right edge tabs, we need to adjust the widget
00693   // rects and clip rects so that the edges don't get drawn.
00694   if (aWidgetType == NS_THEME_TAB_LEFT_EDGE || aWidgetType == NS_THEME_TAB_RIGHT_EDGE) {
00695     // HACK ALERT: There appears to be no way to really obtain this value, so we're forced
00696     // to just use the default value for Luna (which also happens to be correct for
00697     // all the other skins I've tried).
00698     PRInt32 edgeSize = 2;
00699     
00700     // Armed with the size of the edge, we now need to either shift to the left or to the
00701     // right.  The clip rect won't include this extra area, so we know that we're
00702     // effectively shifting the edge out of view (such that it won't be painted).
00703     if (aWidgetType == NS_THEME_TAB_LEFT_EDGE)
00704       // The right edge should not be drawn.  Extend our rect by the edge size.
00705       widgetRect.right += edgeSize;
00706     else
00707       // The left edge should not be drawn.  Move the widget rect's left coord back.
00708       widgetRect.left -= edgeSize;
00709   }
00710   
00711   drawThemeBG(theme, hdc, part, state, &widgetRect, &clipRect);
00712 
00713   // Draw focus rectangles for XP HTML checkboxes and radio buttons
00714   // XXX it'd be nice to draw these outside of the frame
00715   if ((aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO)
00716       && aFrame->GetContent()->IsContentOfType(nsIContent::eHTML)) {
00717       PRInt32 contentState ;
00718       contentState = GetContentState(aFrame, aWidgetType);  
00719             
00720       if (contentState & NS_EVENT_STATE_FOCUS) {
00721         // setup DC to make DrawFocusRect draw correctly
00722         ::SetBrushOrgEx(hdc, widgetRect.left, widgetRect.top, NULL);
00723         PRInt32 oldColor;
00724         oldColor = ::SetTextColor(hdc, 0);
00725         // draw focus rectangle
00726         ::DrawFocusRect(hdc, &widgetRect);
00727         ::SetTextColor(hdc, oldColor);
00728       }
00729   }
00730   return NS_OK;
00731 }
00732 
00733 NS_IMETHODIMP
00734 nsNativeThemeWin::GetWidgetBorder(nsIDeviceContext* aContext, 
00735                                   nsIFrame* aFrame,
00736                                   PRUint8 aWidgetType,
00737                                   nsMargin* aResult)
00738 {
00739   HANDLE theme = GetTheme(aWidgetType);
00740   if (!theme)
00741     return ClassicGetWidgetBorder(aContext, aFrame, aWidgetType, aResult); 
00742 
00743   (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
00744 
00745   if (!WidgetIsContainer(aWidgetType) ||
00746       aWidgetType == NS_THEME_TOOLBOX || aWidgetType == NS_THEME_TOOLBAR || 
00747       aWidgetType == NS_THEME_STATUSBAR || 
00748       aWidgetType == NS_THEME_RESIZER || aWidgetType == NS_THEME_TAB_PANEL ||
00749       aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL ||
00750       aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL)
00751     return NS_OK; // Don't worry about it.
00752  
00753   if (!getThemeContentRect)
00754     return NS_ERROR_FAILURE;
00755 
00756   PRInt32 part, state;
00757   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
00758   if (NS_FAILED(rv))
00759     return rv;
00760 
00761   // Get our info.
00762   RECT outerRect; // Create a fake outer rect.
00763   outerRect.top = outerRect.left = 100;
00764   outerRect.right = outerRect.bottom = 200;
00765   RECT contentRect(outerRect);
00766   HRESULT res = getThemeContentRect(theme, NULL, part, state, &outerRect, &contentRect);
00767   
00768   if (FAILED(res))
00769     return NS_ERROR_FAILURE;
00770 
00771   // Now compute the delta in each direction and place it in our
00772   // nsMargin struct.
00773   aResult->top = contentRect.top - outerRect.top;
00774   aResult->bottom = outerRect.bottom - contentRect.bottom;
00775   aResult->left = contentRect.left - outerRect.left;
00776   aResult->right = outerRect.right - contentRect.right;
00777 
00778   // Remove the edges for tabs that are before or after the selected tab,
00779   if (aWidgetType == NS_THEME_TAB_LEFT_EDGE)
00780     // Remove the right edge, since we won't be drawing it.
00781     aResult->right = 0;
00782   else if (aWidgetType == NS_THEME_TAB_RIGHT_EDGE)
00783     // Remove the left edge, since we won't be drawing it.
00784     aResult->left = 0;
00785 
00786   if (aFrame && aWidgetType == NS_THEME_TEXTFIELD) {
00787     nsIContent* content = aFrame->GetContent();
00788     if (content && content->IsContentOfType(nsIContent::eHTML)) {
00789       // We need to pad textfields by 1 pixel, since the caret will draw
00790       // flush against the edge by default if we don't.
00791       aResult->left++;
00792       aResult->right++;
00793     }
00794   }
00795 
00796   return NS_OK;
00797 }
00798 
00799 PRBool
00800 nsNativeThemeWin::GetWidgetPadding(nsIDeviceContext* aContext, 
00801                                    nsIFrame* aFrame,
00802                                    PRUint8 aWidgetType,
00803                                    nsMargin* aResult)
00804 {
00805   return PR_FALSE;
00806 }
00807 
00808 NS_IMETHODIMP
00809 nsNativeThemeWin::GetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
00810                                        PRUint8 aWidgetType,
00811                                        nsSize* aResult, PRBool* aIsOverridable)
00812 {
00813   (*aResult).width = (*aResult).height = 0;
00814   *aIsOverridable = PR_TRUE;
00815 
00816   HANDLE theme = GetTheme(aWidgetType);
00817   if (!theme)
00818     return ClassicGetMinimumWidgetSize(aContext, aFrame, aWidgetType, aResult, aIsOverridable);
00819  
00820   if (aWidgetType == NS_THEME_TOOLBOX || aWidgetType == NS_THEME_TOOLBAR || 
00821       aWidgetType == NS_THEME_STATUSBAR || aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
00822       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
00823       aWidgetType == NS_THEME_TAB_PANELS || aWidgetType == NS_THEME_TAB_PANEL ||
00824       aWidgetType == NS_THEME_LISTBOX || aWidgetType == NS_THEME_TREEVIEW)
00825     return NS_OK; // Don't worry about it.
00826 
00827   if (!getThemePartSize)
00828     return NS_ERROR_FAILURE;
00829   
00830   // Call GetSystemMetrics to determine size for WinXP scrollbars
00831   // (GetThemeSysSize API returns the optimal size for the theme, but 
00832   //  Windows appears to always use metrics when drawing standard scrollbars)
00833   switch (aWidgetType) {
00834     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
00835     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
00836     case NS_THEME_SCROLLBAR_BUTTON_UP:
00837     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
00838     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
00839     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
00840     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
00841     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
00842     case NS_THEME_DROPDOWN_BUTTON: 
00843       return ClassicGetMinimumWidgetSize(aContext, aFrame, aWidgetType, aResult, aIsOverridable);
00844   }
00845 
00846   PRInt32 part, state;
00847   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
00848   if (NS_FAILED(rv))
00849     return rv;
00850 
00851   HDC hdc = ((nsRenderingContextWin*)aContext)->mDC;
00852   if (!hdc)
00853     return NS_ERROR_FAILURE;
00854 
00855   PRInt32 sizeReq = 1; // Best-fit size.
00856   if (aWidgetType == NS_THEME_PROGRESSBAR ||
00857       aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL)
00858     sizeReq = 0; // Best-fit size for progress meters is too large for most 
00859                  // themes.
00860                  // In our app, we want these widgets to be able to really shrink down,
00861                  // so use the min-size request value (of 0).
00862   
00863   SIZE sz;
00864   getThemePartSize(theme, hdc, part, state, NULL, sizeReq, &sz);
00865   aResult->width = sz.cx;
00866   aResult->height = sz.cy;
00867 
00868   return NS_OK;
00869 }
00870 
00871 NS_IMETHODIMP
00872 nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, PRUint8 aWidgetType, 
00873                                      nsIAtom* aAttribute, PRBool* aShouldRepaint)
00874 {
00875   // Some widget types just never change state.
00876   if (aWidgetType == NS_THEME_TOOLBOX || aWidgetType == NS_THEME_TOOLBAR ||
00877       aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL || 
00878       aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL || 
00879       aWidgetType == NS_THEME_STATUSBAR || aWidgetType == NS_THEME_STATUSBAR_PANEL ||
00880       aWidgetType == NS_THEME_STATUSBAR_RESIZER_PANEL ||
00881       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
00882       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
00883       aWidgetType == NS_THEME_PROGRESSBAR ||
00884       aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL ||
00885       aWidgetType == NS_THEME_TOOLTIP ||
00886       aWidgetType == NS_THEME_TAB_PANELS ||
00887       aWidgetType == NS_THEME_TAB_PANEL) {
00888     *aShouldRepaint = PR_FALSE;
00889     return NS_OK;
00890   }
00891 
00892   // XXXdwh Not sure what can really be done here.  Can at least guess for
00893   // specific widgets that they're highly unlikely to have certain states.
00894   // For example, a toolbar doesn't care about any states.
00895   if (!aAttribute) {
00896     // Hover/focus/active changed.  Always repaint.
00897     *aShouldRepaint = PR_TRUE;
00898   }
00899   else {
00900     // Check the attribute to see if it's relevant.  
00901     // disabled, checked, dlgtype, default, etc.
00902     *aShouldRepaint = PR_FALSE;
00903     if (aAttribute == mDisabledAtom || aAttribute == mCheckedAtom ||
00904         aAttribute == mSelectedAtom || aAttribute == mReadOnlyAtom)
00905       *aShouldRepaint = PR_TRUE;
00906   }
00907 
00908   return NS_OK;
00909 }
00910 
00911 void
00912 nsNativeThemeWin::CloseData()
00913 {
00914   if (mToolbarTheme) {
00915     closeTheme(mToolbarTheme);
00916     mToolbarTheme = NULL;
00917   }
00918   if (mScrollbarTheme) {
00919     closeTheme(mScrollbarTheme);
00920     mScrollbarTheme = NULL;
00921   }
00922   if (mRebarTheme) {
00923     closeTheme(mRebarTheme);
00924     mRebarTheme = NULL;
00925   }
00926   if (mProgressTheme) {
00927     closeTheme(mProgressTheme);
00928     mProgressTheme = NULL;
00929   }
00930   if (mButtonTheme) {
00931     closeTheme(mButtonTheme);
00932     mButtonTheme = NULL;
00933   }
00934   if (mTextFieldTheme) {
00935     closeTheme(mTextFieldTheme);
00936     mTextFieldTheme = NULL;
00937   }
00938   if (mTooltipTheme) {
00939     closeTheme(mTooltipTheme);
00940     mTooltipTheme = NULL;
00941   }
00942   if (mStatusbarTheme) {
00943     closeTheme(mStatusbarTheme);
00944     mStatusbarTheme = NULL;
00945   }
00946   if (mTabTheme) {
00947     closeTheme(mTabTheme);
00948     mTabTheme = NULL;
00949   }
00950   if (mTreeViewTheme) {
00951     closeTheme(mTreeViewTheme);
00952     mTreeViewTheme = NULL;
00953   }
00954   if (mComboBoxTheme) {
00955     closeTheme(mComboBoxTheme);
00956     mComboBoxTheme = NULL;
00957   }
00958   if (mHeaderTheme) {
00959     closeTheme(mHeaderTheme);
00960     mHeaderTheme = NULL;
00961   }
00962 }
00963 
00964 NS_IMETHODIMP
00965 nsNativeThemeWin::ThemeChanged()
00966 {
00967   CloseData();
00968   return NS_OK;
00969 }
00970 
00971 PRBool 
00972 nsNativeThemeWin::ThemeSupportsWidget(nsPresContext* aPresContext,
00973                                       nsIFrame* aFrame,
00974                                       PRUint8 aWidgetType)
00975 {
00976   // XXXdwh We can go even further and call the API to ask if support exists for
00977   // specific widgets.
00978 
00979   if (aPresContext && !aPresContext->PresShell()->IsThemeSupportEnabled())
00980     return PR_FALSE;
00981 
00982   HANDLE theme = NULL;
00983   if (aWidgetType == NS_THEME_CHECKBOX_CONTAINER)
00984     theme = GetTheme(NS_THEME_CHECKBOX);
00985   else if (aWidgetType == NS_THEME_RADIO_CONTAINER)
00986     theme = GetTheme(NS_THEME_RADIO);
00987   else
00988     theme = GetTheme(aWidgetType);
00989 
00990   if ((theme) || (!theme && ClassicThemeSupportsWidget(aPresContext, aFrame, aWidgetType)))
00991     // turn off theming for some HTML widgets styled by the page
00992     return (!IsWidgetStyled(aPresContext, aFrame, aWidgetType));
00993   
00994   return PR_FALSE;
00995 }
00996 
00997 PRBool 
00998 nsNativeThemeWin::WidgetIsContainer(PRUint8 aWidgetType)
00999 {
01000   // XXXdwh At some point flesh all of this out.
01001   if (aWidgetType == NS_THEME_DROPDOWN_BUTTON || 
01002       aWidgetType == NS_THEME_RADIO ||
01003       aWidgetType == NS_THEME_CHECKBOX)
01004     return PR_FALSE;
01005   return PR_TRUE;
01006 }
01007 
01008 
01009 /* Windows 9x/NT/2000/Classic XP Theme Support */
01010 
01011 PRBool 
01012 nsNativeThemeWin::ClassicThemeSupportsWidget(nsPresContext* aPresContext,
01013                                       nsIFrame* aFrame,
01014                                       PRUint8 aWidgetType)
01015 {
01016   switch (aWidgetType) {
01017     case NS_THEME_BUTTON:
01018     case NS_THEME_TEXTFIELD:
01019     case NS_THEME_CHECKBOX:
01020     case NS_THEME_RADIO:
01021     case NS_THEME_SCROLLBAR_BUTTON_UP:
01022     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
01023     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
01024     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
01025     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
01026     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
01027     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
01028     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
01029     case NS_THEME_DROPDOWN_BUTTON:
01030     case NS_THEME_SPINNER_UP_BUTTON:
01031     case NS_THEME_SPINNER_DOWN_BUTTON:
01032     case NS_THEME_LISTBOX:
01033     case NS_THEME_TREEVIEW:
01034     case NS_THEME_DROPDOWN_TEXTFIELD:
01035     case NS_THEME_DROPDOWN:
01036     case NS_THEME_TOOLTIP:
01037     case NS_THEME_STATUSBAR:
01038     case NS_THEME_STATUSBAR_PANEL:
01039     case NS_THEME_STATUSBAR_RESIZER_PANEL:
01040     case NS_THEME_RESIZER:
01041     case NS_THEME_PROGRESSBAR:
01042     case NS_THEME_PROGRESSBAR_VERTICAL:
01043     case NS_THEME_PROGRESSBAR_CHUNK:
01044     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
01045     case NS_THEME_TAB:
01046     case NS_THEME_TAB_LEFT_EDGE:
01047     case NS_THEME_TAB_RIGHT_EDGE:
01048     case NS_THEME_TAB_PANEL:
01049     case NS_THEME_TAB_PANELS:
01050       return PR_TRUE;
01051   }
01052   return PR_FALSE;
01053 }
01054 
01055 nsresult
01056 nsNativeThemeWin::ClassicGetWidgetBorder(nsIDeviceContext* aContext, 
01057                                   nsIFrame* aFrame,
01058                                   PRUint8 aWidgetType,
01059                                   nsMargin* aResult)
01060 {
01061   switch (aWidgetType) {
01062     case NS_THEME_BUTTON: {
01063       const nsStyleUserInterface *uiData = aFrame->GetStyleUserInterface();
01064       if (uiData->mUserFocus == NS_STYLE_USER_FOCUS_IGNORE) {
01065         // use different padding for non-focusable buttons
01066         (*aResult).top = (*aResult).left = 1;
01067         (*aResult).bottom = (*aResult).right = 2;
01068       }
01069       else
01070         (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 3; 
01071       break;  
01072     }
01073     case NS_THEME_STATUSBAR:
01074       (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
01075       (*aResult).top = 2;
01076       break;
01077     case NS_THEME_LISTBOX:
01078     case NS_THEME_TREEVIEW:
01079     case NS_THEME_DROPDOWN:
01080     case NS_THEME_DROPDOWN_TEXTFIELD:
01081     case NS_THEME_TAB:
01082     case NS_THEME_TAB_LEFT_EDGE:
01083     case NS_THEME_TAB_RIGHT_EDGE:
01084       (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 2;
01085       break;
01086     case NS_THEME_TEXTFIELD: {
01087       (*aResult).top = (*aResult).bottom = 2;
01088       nsIContent* content = aFrame->GetContent();
01089       if (content && content->IsContentOfType(nsIContent::eHTML))
01090         // HTML text-fields need extra padding
01091         (*aResult).left = (*aResult).right = 3;
01092       else
01093         (*aResult).left = (*aResult).right = 2;
01094       break;
01095     }
01096     case NS_THEME_STATUSBAR_PANEL:
01097     case NS_THEME_STATUSBAR_RESIZER_PANEL: {
01098       (*aResult).top = 1;      
01099       (*aResult).left = 1;
01100       (*aResult).bottom = 1;
01101       (*aResult).right = aFrame->GetNextSibling() ? 3 : 1;
01102       break;
01103     }    
01104     case NS_THEME_TOOLTIP:
01105       (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1;
01106       break;
01107     case NS_THEME_PROGRESSBAR:
01108     case NS_THEME_PROGRESSBAR_VERTICAL:
01109       (*aResult).top = (*aResult).left = (*aResult).bottom = (*aResult).right = 1;
01110       break;
01111     default:
01112       (*aResult).top = (*aResult).bottom = (*aResult).left = (*aResult).right = 0;
01113       break;
01114   }
01115   return NS_OK;
01116 }
01117 
01118 nsresult
01119 nsNativeThemeWin::ClassicGetMinimumWidgetSize(nsIRenderingContext* aContext, nsIFrame* aFrame,
01120                                        PRUint8 aWidgetType,
01121                                        nsSize* aResult, PRBool* aIsOverridable)
01122 {
01123   (*aResult).width = (*aResult).height = 0;
01124   *aIsOverridable = PR_TRUE;
01125   switch (aWidgetType) {
01126     case NS_THEME_RADIO:
01127     case NS_THEME_CHECKBOX: 
01128       (*aResult).width = (*aResult).height = 13;
01129       break;
01130     case NS_THEME_SCROLLBAR_BUTTON_UP:
01131     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
01132       (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
01133       (*aResult).height = ::GetSystemMetrics(SM_CYVSCROLL);
01134       *aIsOverridable = PR_FALSE;
01135       break;
01136     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
01137     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
01138       (*aResult).width = ::GetSystemMetrics(SM_CXHSCROLL);
01139       (*aResult).height = ::GetSystemMetrics(SM_CYHSCROLL);
01140       *aIsOverridable = PR_FALSE;
01141       break;
01142     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
01143       // XXX HACK We should be able to have a minimum height for the scrollbar
01144       // track.  However, this causes problems when uncollapsing a scrollbar
01145       // inside a tree.  See bug 201379 for details.
01146 
01147         //      (*aResult).height = ::GetSystemMetrics(SM_CYVTHUMB) << 1;
01148       break;
01149     case NS_THEME_DROPDOWN_BUTTON:
01150       (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL);
01151       break;
01152     case NS_THEME_DROPDOWN:
01153     case NS_THEME_BUTTON:
01154     case NS_THEME_LISTBOX:
01155     case NS_THEME_TREEVIEW:
01156     case NS_THEME_TEXTFIELD:          
01157     case NS_THEME_DROPDOWN_TEXTFIELD:      
01158     case NS_THEME_STATUSBAR:
01159     case NS_THEME_STATUSBAR_PANEL:      
01160     case NS_THEME_STATUSBAR_RESIZER_PANEL:
01161     case NS_THEME_PROGRESSBAR_CHUNK:
01162     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
01163     case NS_THEME_TOOLTIP:
01164     case NS_THEME_PROGRESSBAR:
01165     case NS_THEME_PROGRESSBAR_VERTICAL:
01166     case NS_THEME_TAB:
01167     case NS_THEME_TAB_LEFT_EDGE:
01168     case NS_THEME_TAB_RIGHT_EDGE:
01169     case NS_THEME_TAB_PANEL:
01170     case NS_THEME_TAB_PANELS:
01171       // no minimum widget size
01172       break;
01173     case NS_THEME_RESIZER: {     
01174 #ifndef WINCE
01175       NONCLIENTMETRICS nc;
01176       nc.cbSize = sizeof(nc);
01177       if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nc), &nc, 0))
01178         (*aResult).width = (*aResult).height = abs(nc.lfStatusFont.lfHeight) + 4;
01179       else
01180 #endif
01181         (*aResult).width = (*aResult).height = 15;
01182       break;
01183     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:        
01184       (*aResult).width = ::GetSystemMetrics(SM_CYVTHUMB);
01185       (*aResult).height = (*aResult).width >> 1;
01186       *aIsOverridable = PR_FALSE;
01187       break;
01188     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
01189       (*aResult).height = ::GetSystemMetrics(SM_CXHTHUMB);
01190       (*aResult).width = (*aResult).height >> 1;
01191       *aIsOverridable = PR_FALSE;
01192       break;
01193     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:
01194       (*aResult).width = ::GetSystemMetrics(SM_CXHTHUMB) << 1;
01195       break;
01196     }
01197     default:
01198       return NS_ERROR_FAILURE;
01199   }  
01200   return NS_OK;
01201 }
01202 
01203 
01204 nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, PRUint8 aWidgetType,
01205                                  PRInt32& aPart, PRInt32& aState, PRBool& aFocused)
01206 {  
01207   switch (aWidgetType) {
01208     case NS_THEME_BUTTON: {
01209       PRInt32 contentState;
01210 
01211       aPart = DFC_BUTTON;
01212       aState = DFCS_BUTTONPUSH;
01213       aFocused = PR_FALSE;
01214 
01215       contentState = GetContentState(aFrame, aWidgetType);
01216       if (IsDisabled(aFrame))
01217         aState |= DFCS_INACTIVE;
01218       else {
01219         if (contentState & NS_EVENT_STATE_ACTIVE && contentState & NS_EVENT_STATE_HOVER) {
01220           aState |= DFCS_PUSHED;
01221           const nsStyleUserInterface *uiData = aFrame->GetStyleUserInterface();
01222           // The down state is flat if the button is focusable
01223           if (uiData->mUserFocus == NS_STYLE_USER_FOCUS_NORMAL) {
01224 #ifndef WINCE
01225             if (!aFrame->GetContent()->IsContentOfType(nsIContent::eHTML))
01226               aState |= DFCS_FLAT;
01227 #endif
01228             aFocused = PR_TRUE;
01229           }
01230         }
01231         if ((contentState & NS_EVENT_STATE_FOCUS) || 
01232           (aState == DFCS_BUTTONPUSH && IsDefaultButton(aFrame))) {
01233           aFocused = PR_TRUE;          
01234         }
01235 
01236       }
01237 
01238       return NS_OK;
01239     }
01240     case NS_THEME_CHECKBOX:
01241     case NS_THEME_RADIO: {
01242       PRInt32 contentState ;
01243       aFocused = PR_FALSE;
01244 
01245       aPart = DFC_BUTTON;
01246       aState = (aWidgetType == NS_THEME_CHECKBOX) ? DFCS_BUTTONCHECK : DFCS_BUTTONRADIO;
01247       nsIContent* content = aFrame->GetContent();
01248            
01249       if (content->IsContentOfType(nsIContent::eXUL)) {
01250         // XUL
01251         if (aWidgetType == NS_THEME_CHECKBOX) {
01252           if (IsChecked(aFrame))
01253             aState |= DFCS_CHECKED;
01254         }
01255         else
01256           if (IsSelected(aFrame))
01257             aState |= DFCS_CHECKED;
01258         contentState = GetContentState(aFrame, aWidgetType);
01259       }
01260       else {
01261         // HTML
01262 
01263         nsCOMPtr<nsIDOMHTMLInputElement> inputElt(do_QueryInterface(content));
01264         if (inputElt) {
01265           PRBool isChecked = PR_FALSE;
01266           inputElt->GetChecked(&isChecked);
01267           if (isChecked)
01268             aState |= DFCS_CHECKED;
01269         }
01270         contentState = GetContentState(aFrame, aWidgetType);
01271         if (contentState & NS_EVENT_STATE_FOCUS)
01272           aFocused = PR_TRUE;
01273       }
01274 
01275       if (IsDisabled(aFrame))
01276         aState |= DFCS_INACTIVE;
01277       else if (contentState & NS_EVENT_STATE_ACTIVE && contentState & NS_EVENT_STATE_HOVER)
01278         aState |= DFCS_PUSHED;
01279       
01280       return NS_OK;
01281     }
01282     case NS_THEME_LISTBOX:
01283     case NS_THEME_TREEVIEW:
01284     case NS_THEME_TEXTFIELD:
01285     case NS_THEME_DROPDOWN:
01286     case NS_THEME_DROPDOWN_TEXTFIELD:
01287     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
01288     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:     
01289     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
01290     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL:      
01291     case NS_THEME_STATUSBAR:
01292     case NS_THEME_STATUSBAR_PANEL:
01293     case NS_THEME_STATUSBAR_RESIZER_PANEL:
01294     case NS_THEME_PROGRESSBAR_CHUNK:
01295     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
01296     case NS_THEME_TOOLTIP:
01297     case NS_THEME_PROGRESSBAR:
01298     case NS_THEME_PROGRESSBAR_VERTICAL:
01299     case NS_THEME_TAB:
01300     case NS_THEME_TAB_LEFT_EDGE:
01301     case NS_THEME_TAB_RIGHT_EDGE:
01302     case NS_THEME_TAB_PANEL:
01303     case NS_THEME_TAB_PANELS:
01304       // these don't use DrawFrameControl
01305       return NS_OK;
01306     case NS_THEME_DROPDOWN_BUTTON: {
01307 
01308       aPart = DFC_SCROLL;
01309       aState = DFCS_SCROLLCOMBOBOX;
01310       
01311       nsIContent* content = aFrame->GetContent();
01312       nsIFrame* parentFrame = aFrame->GetParent();
01313       nsCOMPtr<nsIMenuFrame> menuFrame(do_QueryInterface(parentFrame));
01314       if (menuFrame || (content && content->IsContentOfType(nsIContent::eHTML)) )
01315          // XUL menu lists and HTML selects get state from parent         
01316          aFrame = parentFrame;
01317          // XXX the button really shouldn't depress when clicking the 
01318          // parent, but the button frame is never :active for these controls..
01319 
01320       if (IsDisabled(aFrame))
01321         aState |= DFCS_INACTIVE;
01322       else {     
01323         PRInt32 eventState = GetContentState(aFrame, aWidgetType);
01324 #ifndef WINCE
01325         if (eventState & NS_EVENT_STATE_HOVER && eventState & NS_EVENT_STATE_ACTIVE)
01326           aState |= DFCS_PUSHED | DFCS_FLAT;
01327 #endif
01328       }
01329 
01330       return NS_OK;
01331     }
01332     case NS_THEME_SCROLLBAR_BUTTON_UP:
01333     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
01334     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
01335     case NS_THEME_SCROLLBAR_BUTTON_RIGHT: {
01336       PRInt32 contentState;
01337 
01338       aPart = DFC_SCROLL;
01339       switch (aWidgetType) {
01340         case NS_THEME_SCROLLBAR_BUTTON_UP:
01341           aState = DFCS_SCROLLUP;
01342           break;
01343         case NS_THEME_SCROLLBAR_BUTTON_DOWN:
01344           aState = DFCS_SCROLLDOWN;
01345           break;
01346         case NS_THEME_SCROLLBAR_BUTTON_LEFT:
01347           aState = DFCS_SCROLLLEFT;
01348           break;
01349         case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
01350           aState = DFCS_SCROLLRIGHT;
01351           break;
01352       }      
01353       
01354       if (IsDisabled(aFrame))
01355         aState |= DFCS_INACTIVE;
01356       else {
01357         contentState = GetContentState(aFrame, aWidgetType);
01358 #ifndef WINCE
01359         if (contentState & NS_EVENT_STATE_HOVER && contentState & NS_EVENT_STATE_ACTIVE)
01360           aState |= DFCS_PUSHED | DFCS_FLAT;      
01361 #endif
01362       }
01363 
01364       return NS_OK;
01365     }
01366     case NS_THEME_SPINNER_UP_BUTTON:
01367     case NS_THEME_SPINNER_DOWN_BUTTON: {
01368       PRInt32 contentState;
01369 
01370       aPart = DFC_SCROLL;
01371       switch (aWidgetType) {
01372         case NS_THEME_SPINNER_UP_BUTTON:
01373           aState = DFCS_SCROLLUP;
01374           break;
01375         case NS_THEME_SPINNER_DOWN_BUTTON:
01376           aState = DFCS_SCROLLDOWN;
01377           break;
01378       }      
01379       
01380       if (IsDisabled(aFrame))
01381         aState |= DFCS_INACTIVE;
01382       else {
01383         contentState = GetContentState(aFrame, aWidgetType);
01384         if (contentState & NS_EVENT_STATE_HOVER && contentState & NS_EVENT_STATE_ACTIVE)
01385           aState |= DFCS_PUSHED;
01386       }
01387 
01388       return NS_OK;    
01389     }
01390     case NS_THEME_RESIZER:    
01391       aPart = DFC_SCROLL;
01392       aState = DFCS_SCROLLSIZEGRIP;
01393       return NS_OK;
01394   }
01395   return NS_ERROR_FAILURE;
01396 }
01397 
01398 // Draw classic Windows tab
01399 // (no system API for this, but DrawEdge can draw all the parts of a tab)
01400 static void DrawTab(HDC hdc, const RECT& R, PRInt32 aPosition, PRBool aSelected,
01401                     PRBool aDrawLeft, PRBool aDrawRight)
01402 {
01403   PRInt32 leftFlag, topFlag, rightFlag, lightFlag, shadeFlag;  
01404   RECT topRect, sideRect, bottomRect, lightRect, shadeRect;
01405   PRInt32 selectedOffset, lOffset, rOffset;
01406 
01407   selectedOffset = aSelected ? 1 : 0;
01408   lOffset = aDrawLeft ? 2 : 0;
01409   rOffset = aDrawRight ? 2 : 0;
01410 
01411   // Get info for tab orientation/position (Left, Top, Right, Bottom)
01412   switch (aPosition) {
01413     case BF_LEFT:
01414       leftFlag = BF_TOP; topFlag = BF_LEFT;
01415       rightFlag = BF_BOTTOM;
01416       lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
01417       shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
01418 
01419       ::SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
01420       ::SetRect(&sideRect, R.left+2, R.top, R.right-2+selectedOffset, R.bottom);
01421       ::SetRect(&bottomRect, R.right-2, R.top, R.right, R.bottom);
01422       ::SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);
01423       ::SetRect(&shadeRect, R.left+1, R.bottom-2, R.left+2, R.bottom-1);
01424       break;
01425     case BF_TOP:    
01426       leftFlag = BF_LEFT; topFlag = BF_TOP;
01427       rightFlag = BF_RIGHT;
01428       lightFlag = BF_DIAGONAL_ENDTOPRIGHT;
01429       shadeFlag = BF_DIAGONAL_ENDBOTTOMRIGHT;
01430 
01431       ::SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
01432       ::SetRect(&sideRect, R.left, R.top+2, R.right, R.bottom-1+selectedOffset);
01433       ::SetRect(&bottomRect, R.left, R.bottom-1, R.right, R.bottom);
01434       ::SetRect(&lightRect, R.left, R.top, R.left+3, R.top+3);      
01435       ::SetRect(&shadeRect, R.right-2, R.top+1, R.right-1, R.top+2);      
01436       break;
01437     case BF_RIGHT:    
01438       leftFlag = BF_TOP; topFlag = BF_RIGHT;
01439       rightFlag = BF_BOTTOM;
01440       lightFlag = BF_DIAGONAL_ENDTOPLEFT;
01441       shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
01442 
01443       ::SetRect(&topRect, R.left, R.top+lOffset, R.right, R.bottom-rOffset);
01444       ::SetRect(&sideRect, R.left+2-selectedOffset, R.top, R.right-2, R.bottom);
01445       ::SetRect(&bottomRect, R.left, R.top, R.left+2, R.bottom);
01446       ::SetRect(&lightRect, R.right-3, R.top, R.right-1, R.top+2);
01447       ::SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
01448       break;
01449     case BF_BOTTOM:    
01450       leftFlag = BF_LEFT; topFlag = BF_BOTTOM;
01451       rightFlag = BF_RIGHT;
01452       lightFlag = BF_DIAGONAL_ENDTOPLEFT;
01453       shadeFlag = BF_DIAGONAL_ENDBOTTOMLEFT;
01454 
01455       ::SetRect(&topRect, R.left+lOffset, R.top, R.right-rOffset, R.bottom);
01456       ::SetRect(&sideRect, R.left, R.top+2-selectedOffset, R.right, R.bottom-2);
01457       ::SetRect(&bottomRect, R.left, R.top, R.right, R.top+2);
01458       ::SetRect(&lightRect, R.left, R.bottom-3, R.left+2, R.bottom-1);
01459       ::SetRect(&shadeRect, R.right-2, R.bottom-3, R.right, R.bottom-1);
01460       break;
01461   }
01462 
01463   // Background
01464   ::FillRect(hdc, &R, (HBRUSH) (COLOR_3DFACE+1) );
01465 
01466   // Tab "Top"
01467   ::DrawEdge(hdc, &topRect, EDGE_RAISED, BF_SOFT | topFlag);
01468 
01469   // Tab "Bottom"
01470   if (!aSelected)
01471     ::DrawEdge(hdc, &bottomRect, EDGE_RAISED, BF_SOFT | topFlag);
01472 
01473   // Tab "Sides"
01474   if (!aDrawLeft)
01475     leftFlag = 0;
01476   if (!aDrawRight)
01477     rightFlag = 0;
01478   ::DrawEdge(hdc, &sideRect, EDGE_RAISED, BF_SOFT | leftFlag | rightFlag);
01479 
01480   // Tab Diagonal Corners
01481   if (aDrawLeft)
01482     ::DrawEdge(hdc, &lightRect, EDGE_RAISED, BF_SOFT | lightFlag);
01483 
01484   if (aDrawRight)
01485     ::DrawEdge(hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag);
01486 }
01487 
01488 nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aContext,
01489                                   nsIFrame* aFrame,
01490                                   PRUint8 aWidgetType,
01491                                   const nsRect& aRect,
01492                                   const nsRect& aClipRect)
01493 {         
01494   PRInt32 part, state;
01495   PRBool focused;
01496   nsresult rv;
01497   rv = ClassicGetThemePartAndState(aFrame, aWidgetType, part, state, focused);
01498   if (NS_FAILED(rv))
01499     return rv;
01500 
01501   nsTransform2D* transformMatrix;
01502   aContext->GetCurrentTransform(transformMatrix);
01503   RECT widgetRect;
01504        nsRect tr(aRect);
01505        transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height);
01506   GetNativeRect(tr, widgetRect); 
01507 
01508   HDC hdc = NS_STATIC_CAST(nsRenderingContextWin*, aContext)->mDC;
01509 
01510   switch (aWidgetType) { 
01511     // Draw button
01512     case NS_THEME_BUTTON: {
01513       if (focused) {
01514         // draw dark button focus border first
01515         HBRUSH brush;        
01516         brush = ::GetSysColorBrush(COLOR_3DDKSHADOW);
01517         if (brush)
01518           ::FrameRect(hdc, &widgetRect, brush);
01519         InflateRect(&widgetRect, -1, -1);
01520       }
01521       // fall-through...
01522     }
01523     // Draw controls supported by DrawFrameControl
01524     case NS_THEME_CHECKBOX:
01525     case NS_THEME_RADIO:
01526     case NS_THEME_SCROLLBAR_BUTTON_UP:
01527     case NS_THEME_SCROLLBAR_BUTTON_DOWN:
01528     case NS_THEME_SCROLLBAR_BUTTON_LEFT:
01529     case NS_THEME_SCROLLBAR_BUTTON_RIGHT:
01530     case NS_THEME_SPINNER_UP_BUTTON:
01531     case NS_THEME_SPINNER_DOWN_BUTTON:
01532     case NS_THEME_DROPDOWN_BUTTON:
01533     case NS_THEME_RESIZER: { 
01534       PRInt32 oldTA;
01535       // setup DC to make DrawFrameControl draw correctly
01536       oldTA = ::SetTextAlign(hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
01537       ::DrawFrameControl(hdc, &widgetRect, part, state);
01538       ::SetTextAlign(hdc, oldTA);
01539 
01540       // Draw focus rectangles for HTML checkboxes and radio buttons
01541       // XXX it'd be nice to draw these outside of the frame
01542       if (focused && (aWidgetType == NS_THEME_CHECKBOX || aWidgetType == NS_THEME_RADIO)) {
01543         // setup DC to make DrawFocusRect draw correctly
01544         ::SetBrushOrgEx(hdc, widgetRect.left, widgetRect.top, NULL);
01545         PRInt32 oldColor;
01546         oldColor = ::SetTextColor(hdc, 0);
01547         // draw focus rectangle
01548         ::DrawFocusRect(hdc, &widgetRect);
01549         ::SetTextColor(hdc, oldColor);
01550       }
01551 
01552       return NS_OK;
01553     }
01554     // Draw controls with 2px 3D inset border
01555     case NS_THEME_TEXTFIELD:
01556     case NS_THEME_LISTBOX:
01557     case NS_THEME_DROPDOWN:
01558     case NS_THEME_DROPDOWN_TEXTFIELD: {
01559       // Draw inset edge
01560       ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
01561 
01562       // Fill in background
01563       if (IsDisabled(aFrame) ||
01564           (aFrame->GetContent()->IsContentOfType(nsIContent::eXUL) &&
01565            IsReadOnly(aFrame)))
01566         ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_BTNFACE+1));
01567       else
01568         ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_WINDOW+1));
01569       return NS_OK;
01570     }
01571     case NS_THEME_TREEVIEW: {
01572       // Draw inset edge
01573       ::DrawEdge(hdc, &widgetRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
01574 
01575       // Fill in window color background
01576       ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_WINDOW+1));
01577       
01578       return NS_OK;
01579     }
01580     // Draw ToolTip background
01581     case NS_THEME_TOOLTIP:
01582       HBRUSH brush;
01583       brush = ::GetSysColorBrush(COLOR_3DDKSHADOW);
01584       if (brush)
01585         ::FrameRect(hdc, &widgetRect, brush);
01586       InflateRect(&widgetRect, -1, -1);
01587       ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_INFOBK+1));
01588       return NS_OK;
01589     // Draw 3D face background controls
01590     case NS_THEME_PROGRESSBAR:
01591     case NS_THEME_PROGRESSBAR_VERTICAL:
01592       // Draw 3D border
01593       ::DrawEdge(hdc, &widgetRect, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE);
01594       InflateRect(&widgetRect, -1, -1);
01595       // fall through
01596     case NS_THEME_TAB_PANEL:
01597     case NS_THEME_STATUSBAR:
01598     case NS_THEME_STATUSBAR_RESIZER_PANEL: {
01599       ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_BTNFACE+1));
01600       return NS_OK;
01601     }
01602     // Draw 3D inset statusbar panel
01603     case NS_THEME_STATUSBAR_PANEL: {
01604       if (aFrame->GetNextSibling())
01605         widgetRect.right -= 2; // space between sibling status panels
01606 
01607       ::DrawEdge(hdc, &widgetRect, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE);
01608       return NS_OK;  
01609     }
01610     // Draw scrollbar thumb
01611     case NS_THEME_SCROLLBAR_THUMB_VERTICAL:
01612     case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL:
01613       ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_MIDDLE);
01614       return NS_OK;
01615     // Draw scrollbar track background
01616     case NS_THEME_SCROLLBAR_TRACK_VERTICAL:
01617     case NS_THEME_SCROLLBAR_TRACK_HORIZONTAL: {
01618 
01619       // Windows fills in the scrollbar track differently 
01620       // depending on whether these are equal
01621       DWORD color3D, colorScrollbar, colorWindow;
01622 
01623       color3D = ::GetSysColor(COLOR_3DFACE);      
01624       colorWindow = ::GetSysColor(COLOR_WINDOW);
01625       colorScrollbar = ::GetSysColor(COLOR_SCROLLBAR);
01626       
01627       if ((color3D != colorScrollbar) && (colorWindow != colorScrollbar))
01628         // Use solid brush
01629         ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_SCROLLBAR+1));
01630       else
01631       {
01632         // Use checkerboard pattern brush
01633         HBRUSH brush, oldBrush = NULL;
01634         HBITMAP patBmp = NULL;
01635         COLORREF oldBackColor, oldForeColor;
01636         static WORD patBits[8] = {
01637           0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55
01638         };
01639         
01640         patBmp = ::CreateBitmap(8, 8, 1, 1, patBits);
01641         if (patBmp) {
01642           brush = (HBRUSH) ::CreatePatternBrush(patBmp);
01643           if (brush) {        
01644             oldForeColor = ::SetTextColor(hdc, ::GetSysColor(COLOR_3DHILIGHT));
01645             oldBackColor = ::SetBkColor(hdc, color3D);
01646 
01647 #ifndef WINCE
01648             ::UnrealizeObject(brush);
01649 #endif
01650             ::SetBrushOrgEx(hdc, widgetRect.left, widgetRect.top, NULL);
01651             oldBrush = (HBRUSH) ::SelectObject(hdc, brush);
01652 
01653             ::FillRect(hdc, &widgetRect, brush);
01654 
01655             ::SetTextColor(hdc, oldForeColor);
01656             ::SetBkColor(hdc, oldBackColor);
01657             ::SelectObject(hdc, oldBrush);
01658             ::DeleteObject(brush);          
01659           }
01660           else
01661             ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_SCROLLBAR+1));
01662           
01663           ::DeleteObject(patBmp);
01664         }
01665       }
01666       // XXX should invert the part of the track being clicked here
01667       // but the track is never :active
01668       return NS_OK;
01669     }
01670     case NS_THEME_PROGRESSBAR_CHUNK:
01671     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
01672       ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1));
01673       return NS_OK;
01674     // Draw Tab
01675     case NS_THEME_TAB:
01676     case NS_THEME_TAB_LEFT_EDGE:
01677     case NS_THEME_TAB_RIGHT_EDGE: {
01678       DrawTab(hdc, widgetRect,
01679         IsBottomTab(aFrame) ? BF_BOTTOM : BF_TOP, 
01680         IsSelectedTab(aFrame),
01681         aWidgetType != NS_THEME_TAB_RIGHT_EDGE,
01682         aWidgetType != NS_THEME_TAB_LEFT_EDGE);      
01683 
01684       return NS_OK;
01685     }
01686     case NS_THEME_TAB_PANELS:
01687       ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_SOFT | BF_MIDDLE |
01688           BF_LEFT | BF_RIGHT | BF_BOTTOM);
01689       return NS_OK;
01690 
01691   }
01692   return NS_ERROR_FAILURE;
01693 }
01694 
01695 
01697 // Creation Routine
01699 NS_METHOD NS_NewNativeTheme(nsISupports *aOuter, REFNSIID aIID, void **aResult)
01700 {
01701   if (aOuter)
01702     return NS_ERROR_NO_AGGREGATION;
01703 
01704   nsNativeThemeWin* theme = new nsNativeThemeWin();
01705   if (!theme)
01706     return NS_ERROR_OUT_OF_MEMORY;
01707   return theme->QueryInterface(aIID, aResult);
01708 }