Back to index

lightning-sunbird  0.9+nobinonly
nsLookAndFeel.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  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Michael Lowe <michael.lowe@bigfoot.com>
00024  *   Jens Bannmann <jens.b@web.de>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsLookAndFeel.h"
00041 #include "nsXPLookAndFeel.h"
00042 #include <windows.h>
00043 #include <shellapi.h>
00044 #include "nsWindow.h"
00045  
00046 #ifndef WINCE
00047 typedef UINT (CALLBACK *SHAppBarMessagePtr)(DWORD, PAPPBARDATA);
00048 SHAppBarMessagePtr gSHAppBarMessage = NULL;
00049 static HINSTANCE gShell32DLLInst = NULL;
00050 #endif
00051 
00052 nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel()
00053 {
00054 #ifndef WINCE
00055   gShell32DLLInst = LoadLibrary("Shell32.dll");
00056   if (gShell32DLLInst)
00057   {
00058       gSHAppBarMessage = (SHAppBarMessagePtr) GetProcAddress(gShell32DLLInst,
00059                                                              "SHAppBarMessage");
00060   }
00061 #endif
00062 }
00063 
00064 nsLookAndFeel::~nsLookAndFeel()
00065 {
00066 #ifndef WINCE
00067    if (gShell32DLLInst)
00068    {
00069        FreeLibrary(gShell32DLLInst);
00070        gShell32DLLInst = NULL;
00071        gSHAppBarMessage = NULL;
00072    }
00073 #endif
00074 }
00075 
00076 nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
00077 {
00078   nsresult res = NS_OK;
00079 
00080   int idx;
00081   switch (aID) {
00082     case eColor_WindowBackground:
00083         idx = COLOR_WINDOW;
00084         break;
00085     case eColor_WindowForeground:
00086         idx = COLOR_WINDOWTEXT;
00087         break;
00088     case eColor_WidgetBackground:
00089         idx = COLOR_BTNFACE;
00090         break;
00091     case eColor_WidgetForeground:
00092         idx = COLOR_BTNTEXT;
00093         break;
00094     case eColor_WidgetSelectBackground:
00095         idx = COLOR_HIGHLIGHT;
00096         break;
00097     case eColor_WidgetSelectForeground:
00098         idx = COLOR_HIGHLIGHTTEXT;
00099         break;
00100     case eColor_Widget3DHighlight:
00101         idx = COLOR_BTNHIGHLIGHT;
00102         break;
00103     case eColor_Widget3DShadow:
00104         idx = COLOR_BTNSHADOW;
00105         break;
00106     case eColor_TextBackground:
00107         idx = COLOR_WINDOW;
00108         break;
00109     case eColor_TextForeground:
00110         idx = COLOR_WINDOWTEXT;
00111         break;
00112     case eColor_TextSelectBackground:
00113         idx = COLOR_HIGHLIGHT;
00114         break;
00115     case eColor_TextSelectForeground:
00116         idx = COLOR_HIGHLIGHTTEXT;
00117         break;
00118 
00119     // New CSS 2 Color definitions
00120     case eColor_activeborder:
00121       idx = COLOR_ACTIVEBORDER;
00122       break;
00123     case eColor_activecaption:
00124       idx = COLOR_ACTIVECAPTION;
00125       break;
00126     case eColor_appworkspace:
00127       idx = COLOR_APPWORKSPACE;
00128       break;
00129     case eColor_background:
00130       idx = COLOR_BACKGROUND;
00131       break;
00132     case eColor_buttonface:
00133     case eColor__moz_buttonhoverface:
00134       idx = COLOR_BTNFACE;
00135       break;
00136     case eColor_buttonhighlight:
00137       idx = COLOR_BTNHIGHLIGHT;
00138       break;
00139     case eColor_buttonshadow:
00140       idx = COLOR_BTNSHADOW;
00141       break;
00142     case eColor_buttontext:
00143     case eColor__moz_buttonhovertext:
00144       idx = COLOR_BTNTEXT;
00145       break;
00146     case eColor_captiontext:
00147       idx = COLOR_CAPTIONTEXT;
00148       break;
00149     case eColor_graytext:
00150       idx = COLOR_GRAYTEXT;
00151       break;
00152     case eColor_highlight:
00153     case eColor__moz_menuhover:
00154       idx = COLOR_HIGHLIGHT;
00155       break;
00156     case eColor_highlighttext:
00157     case eColor__moz_menuhovertext:
00158       idx = COLOR_HIGHLIGHTTEXT;
00159       break;
00160     case eColor_inactiveborder:
00161       idx = COLOR_INACTIVEBORDER;
00162       break;
00163     case eColor_inactivecaption:
00164       idx = COLOR_INACTIVECAPTION;
00165       break;
00166     case eColor_inactivecaptiontext:
00167       idx = COLOR_INACTIVECAPTIONTEXT;
00168       break;
00169     case eColor_infobackground:
00170       idx = COLOR_INFOBK;
00171       break;
00172     case eColor_infotext:
00173       idx = COLOR_INFOTEXT;
00174       break;
00175     case eColor_menu:
00176       idx = COLOR_MENU;
00177       break;
00178     case eColor_menutext:
00179       idx = COLOR_MENUTEXT;
00180       break;
00181     case eColor_scrollbar:
00182       idx = COLOR_SCROLLBAR;
00183       break;
00184     case eColor_threeddarkshadow:
00185       idx = COLOR_3DDKSHADOW;
00186       break;
00187     case eColor_threedface:
00188       idx = COLOR_3DFACE;
00189       break;
00190     case eColor_threedhighlight:
00191       idx = COLOR_3DHIGHLIGHT;
00192       break;
00193     case eColor_threedlightshadow:
00194       idx = COLOR_3DLIGHT;
00195       break;
00196     case eColor_threedshadow:
00197       idx = COLOR_3DSHADOW;
00198       break;
00199     case eColor_window:
00200       idx = COLOR_WINDOW;
00201       break;
00202     case eColor_windowframe:
00203       idx = COLOR_WINDOWFRAME;
00204       break;
00205     case eColor_windowtext:
00206       idx = COLOR_WINDOWTEXT;
00207       break;
00208     case eColor__moz_field:
00209       idx = COLOR_WINDOW;
00210       break;
00211     case eColor__moz_fieldtext:
00212       idx = COLOR_WINDOWTEXT;
00213       break;
00214     case eColor__moz_dialog:
00215     case eColor__moz_cellhighlight:
00216       idx = COLOR_3DFACE;
00217       break;
00218     case eColor__moz_dialogtext:
00219     case eColor__moz_cellhighlighttext:
00220       idx = COLOR_WINDOWTEXT;
00221       break;
00222     case eColor__moz_dragtargetzone:
00223       idx = COLOR_HIGHLIGHTTEXT;
00224       break;
00225     case eColor__moz_buttondefault:
00226       idx = COLOR_3DDKSHADOW;
00227       break;
00228     default:
00229       idx = COLOR_WINDOW;
00230       break;
00231     }
00232 
00233   DWORD color = ::GetSysColor(idx);
00234   aColor = COLOREF_2_NSRGB(color);
00235 
00236   return res;
00237 }
00238 
00239 NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
00240 {
00241   nsresult res = nsXPLookAndFeel::GetMetric(aID, aMetric);
00242   if (NS_SUCCEEDED(res))
00243     return res;
00244   res = NS_OK;
00245 
00246   switch (aID) {
00247     case eMetric_WindowTitleHeight:
00248         aMetric = ::GetSystemMetrics(SM_CYCAPTION);
00249         break;
00250 #ifndef WINCE
00251     case eMetric_WindowBorderWidth:
00252         aMetric = ::GetSystemMetrics(SM_CXFRAME);
00253         break;
00254     case eMetric_WindowBorderHeight:
00255         aMetric = ::GetSystemMetrics(SM_CYFRAME);
00256         break;
00257 #endif
00258     case eMetric_Widget3DBorder:
00259         aMetric = ::GetSystemMetrics(SM_CXEDGE);
00260         break;
00261     case eMetric_TextFieldBorder:
00262         aMetric = 3;
00263         break;
00264     case eMetric_TextFieldHeight:
00265         aMetric = 24;
00266         break;
00267     case eMetric_ButtonHorizontalInsidePaddingNavQuirks:
00268         aMetric = 10;
00269         break;
00270     case eMetric_ButtonHorizontalInsidePaddingOffsetNavQuirks:
00271         aMetric = 8;
00272         break;
00273     case eMetric_CheckboxSize:
00274         aMetric = 12;
00275         break;
00276     case eMetric_RadioboxSize:
00277         aMetric = 12;
00278         break;
00279     case eMetric_TextHorizontalInsideMinimumPadding:
00280         aMetric = 3;
00281         break;
00282     case eMetric_TextVerticalInsidePadding:
00283         aMetric = 0;
00284         break;
00285     case eMetric_TextShouldUseVerticalInsidePadding:
00286         aMetric = 0;
00287         break;
00288     case eMetric_TextShouldUseHorizontalInsideMinimumPadding:
00289         aMetric = 1;
00290         break;
00291     case eMetric_ListShouldUseHorizontalInsideMinimumPadding:
00292         aMetric = 0;
00293         break;
00294     case eMetric_ListHorizontalInsideMinimumPadding:
00295         aMetric = 3;
00296         break;
00297     case eMetric_ListShouldUseVerticalInsidePadding:
00298         aMetric = 0;
00299         break;
00300     case eMetric_ListVerticalInsidePadding:
00301         aMetric = 0;
00302         break;
00303     case eMetric_CaretBlinkTime:
00304         aMetric = (PRInt32)::GetCaretBlinkTime();
00305         break;
00306     case eMetric_CaretWidth:
00307         aMetric = 1;
00308         break;
00309     case eMetric_ShowCaretDuringSelection:
00310         aMetric = 0;
00311         break;
00312     case eMetric_SelectTextfieldsOnKeyFocus:
00313         // Select textfield content when focused by kbd
00314         // used by nsEventStateManager::sTextfieldSelectModel
00315         aMetric = 1;
00316         break;
00317     case eMetric_SubmenuDelay:
00318         {
00319         static PRInt32 sSubmenuDelay = -1;
00320 
00321         if (sSubmenuDelay == -1) {
00322           HKEY key;
00323           char value[100];
00324           DWORD length, type;
00325           LONG result;
00326 
00327           sSubmenuDelay = 300;
00328 
00329 #ifndef WINCE
00330           result = ::RegOpenKeyEx(HKEY_CURRENT_USER, 
00331                    "Control Panel\\Desktop", 0, KEY_READ, &key);
00332 
00333           if (result == ERROR_SUCCESS) {
00334             length = sizeof(value);
00335 
00336             result = ::RegQueryValueEx(key, "MenuShowDelay",
00337                      NULL, &type, (LPBYTE)&value, &length);
00338 
00339             ::RegCloseKey(key);
00340 
00341             if (result == ERROR_SUCCESS) {
00342               PRInt32 errorCode;
00343               nsString str; str.AssignWithConversion(value);
00344               PRInt32 submenuDelay = str.ToInteger(&errorCode);
00345               if (errorCode == NS_OK) {
00346                 sSubmenuDelay = submenuDelay;
00347               }
00348             }
00349           }
00350 #endif
00351         }
00352         aMetric = sSubmenuDelay;
00353         }
00354         break;
00355     case eMetric_MenusCanOverlapOSBar:
00356         // we want XUL popups to be able to overlap the task bar.
00357         aMetric = 1;
00358         break;
00359     case eMetric_DragFullWindow:
00360         {
00361         static PRInt32 sDragFullWindow = -1;
00362 #ifndef WINCE
00363         if (sDragFullWindow == -1) {
00364           HKEY key;
00365           char value[100];
00366           DWORD length, type;
00367           LONG result;
00368 
00369 
00370           result = ::RegOpenKeyEx(HKEY_CURRENT_USER, 
00371                    "Control Panel\\Desktop", 0, KEY_READ, &key);
00372 
00373           if (result == ERROR_SUCCESS) {
00374             length = sizeof(value);
00375 
00376             result = ::RegQueryValueEx(key, "DragFullWindows",
00377                      NULL, &type, (LPBYTE)&value, &length);
00378 
00379             ::RegCloseKey(key);
00380 
00381             if (result == ERROR_SUCCESS) {
00382               PRInt32 errorCode;
00383               nsString str; str.AssignWithConversion(value);
00384               sDragFullWindow = str.ToInteger(&errorCode);         
00385             }
00386           }
00387         } 
00388 #endif
00389         aMetric = sDragFullWindow ? 1 : 0;
00390         }
00391         break;
00392 
00393 #ifndef WINCE
00394     case eMetric_DragThresholdX:
00395         // The system metric is the number of pixels at which a drag should
00396         // start.  Our look and feel metric is the number of pixels you can
00397         // move before starting a drag, so subtract 1.
00398 
00399         aMetric = ::GetSystemMetrics(SM_CXDRAG) - 1;
00400         break;
00401     case eMetric_DragThresholdY:
00402         aMetric = ::GetSystemMetrics(SM_CYDRAG) - 1;
00403         break;
00404     case eMetric_UseAccessibilityTheme:
00405         // High contrast is a misnomer under Win32 -- any theme can be used with it, 
00406         // e.g. normal contrast with large fonts, low contrast, etc.
00407         // The high contrast flag really means -- use this theme and don't override it.
00408         HIGHCONTRAST contrastThemeInfo;
00409         contrastThemeInfo.cbSize = sizeof(contrastThemeInfo);
00410         // Need to check return from SystemParametersInfo since 
00411         // SPI_GETHIGHCONTRAST is not supported on Windows NT 
00412         if (SystemParametersInfo(SPI_GETHIGHCONTRAST, 0, &contrastThemeInfo, 0)) {
00413           aMetric = (contrastThemeInfo.dwFlags & HCF_HIGHCONTRASTON) != 0;
00414         }
00415         else {
00416           aMetric = 0;
00417         }
00418         break;
00419     case eMetric_IsScreenReaderActive:
00420       BOOL isScreenReaderActive;
00421       aMetric = SystemParametersInfo(SPI_GETSCREENREADER, 0, &isScreenReaderActive, 0) && 
00422                 isScreenReaderActive;
00423       break;
00424 #endif
00425     case eMetric_ScrollArrowStyle:
00426         aMetric = eMetric_ScrollArrowStyleSingle;
00427         break;
00428     case eMetric_ScrollSliderStyle:
00429         aMetric = eMetric_ScrollThumbStyleProportional;
00430         break;
00431     case eMetric_TreeOpenDelay:
00432         aMetric = 1000;
00433         break;
00434     case eMetric_TreeCloseDelay:
00435         aMetric = 0;
00436         break;
00437     case eMetric_TreeLazyScrollDelay:
00438         aMetric = 150;
00439         break;
00440     case eMetric_TreeScrollDelay:
00441         aMetric = 100;
00442         break;
00443     case eMetric_TreeScrollLinesMax:
00444         aMetric = 3;
00445         break;
00446 #ifndef WINCE
00447     case eMetric_AlertNotificationOrigin:
00448         aMetric = 0;
00449         if (gSHAppBarMessage)
00450         {
00451           // Get task bar window handle
00452           HWND shellWindow = FindWindow("Shell_TrayWnd", NULL);
00453 
00454           if (shellWindow != NULL)
00455           {
00456             // Determine position
00457             APPBARDATA appBarData;
00458             appBarData.hWnd = shellWindow;
00459             appBarData.cbSize = sizeof(appBarData);
00460             if (gSHAppBarMessage(ABM_GETTASKBARPOS, &appBarData))
00461             {
00462               // Set alert origin as a bit field - see nsILookAndFeel.h
00463               // 0 represents bottom right, sliding vertically.
00464               switch(appBarData.uEdge)
00465               {
00466                 case ABE_LEFT:
00467                   aMetric = NS_ALERT_HORIZONTAL | NS_ALERT_LEFT;
00468                   break;
00469                 case ABE_RIGHT:
00470                   aMetric = NS_ALERT_HORIZONTAL;
00471                   break;
00472                 case ABE_TOP:
00473                   aMetric = NS_ALERT_TOP;
00474                   break;
00475                 case ABE_BOTTOM:
00476                   break;
00477               }
00478             }
00479           }
00480         }
00481         break;
00482 #endif
00483 
00484     default:
00485         aMetric = 0;
00486         res = NS_ERROR_FAILURE;
00487     }
00488   return res;
00489 }
00490 
00491 NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetric)
00492 {
00493   nsresult res = nsXPLookAndFeel::GetMetric(aID, aMetric);
00494   if (NS_SUCCEEDED(res))
00495     return res;
00496   res = NS_OK;
00497 
00498   switch (aID) {
00499     case eMetricFloat_TextFieldVerticalInsidePadding:
00500         aMetric = 0.25f;
00501         break;
00502     case eMetricFloat_TextFieldHorizontalInsidePadding:
00503         aMetric = 1.025f;
00504         break;
00505     case eMetricFloat_TextAreaVerticalInsidePadding:
00506         aMetric = 0.40f;
00507         break;
00508     case eMetricFloat_TextAreaHorizontalInsidePadding:
00509         aMetric = 0.40f;
00510         break;
00511     case eMetricFloat_ListVerticalInsidePadding:
00512         aMetric = 0.10f;
00513         break;
00514     case eMetricFloat_ListHorizontalInsidePadding:
00515         aMetric = 0.40f;
00516         break;
00517     case eMetricFloat_ButtonVerticalInsidePadding:
00518         aMetric = 0.25f;
00519         break;
00520     case eMetricFloat_ButtonHorizontalInsidePadding:
00521         aMetric = 0.25f;
00522         break;
00523     default:
00524         aMetric = -1.0;
00525         res = NS_ERROR_FAILURE;
00526     }
00527   return res;
00528 }
00529 
00530 
00531 #ifdef NS_DEBUG
00532 
00533 NS_IMETHODIMP nsLookAndFeel::GetNavSize(const nsMetricNavWidgetID aWidgetID,
00534                                         const nsMetricNavFontID   aFontID, 
00535                                         const PRInt32             aFontSize, 
00536                                         nsSize &aSize)
00537 {
00538   nsresult rv = nsXPLookAndFeel::GetNavSize(aWidgetID, aFontID, aFontSize,
00539                                             aSize);
00540   if (NS_SUCCEEDED(rv))
00541     return rv;
00542 
00543   aSize.width  = 0;
00544   aSize.height = 0;
00545 
00546   if (aFontSize < 1 || aFontSize > 7) {
00547     return NS_ERROR_FAILURE;
00548   }
00549 
00550   PRInt32 kTextFieldWidths[2][7] = {
00551     {106,147,169,211,253,338,506}, // Courier
00552     {152,214,237,281,366,495,732}  // sans-serif
00553   };
00554 
00555   PRInt32 kTextFieldHeights[2][7] = {
00556     {18,21,24,27,33,45,63}, // Courier
00557     {18,21,24,27,34,48,67}  // sans-serif
00558   };
00559 
00560   PRInt32 kTextAreaWidths[2][7] = {
00561     {121,163,184,226,268,352,520}, // Courier
00562     {163,226,247,289,373,499,730}  // sans-serif
00563   };
00564 
00565   PRInt32 kTextAreaHeights[2][7] = {
00566     {40,44,48,52,60,76,100}, // Courier
00567     {40,44,48,52,62,80,106}  // sans-serif
00568   };
00569 
00570   switch (aWidgetID) {
00571     case eMetricSize_TextField:
00572       aSize.width  = kTextFieldWidths[aFontID][aFontSize-1];
00573       aSize.height = kTextFieldHeights[aFontID][aFontSize-1];
00574       break;
00575     case eMetricSize_TextArea:
00576       aSize.width  = kTextAreaWidths[aFontID][aFontSize-1];
00577       aSize.height = kTextAreaHeights[aFontID][aFontSize-1];
00578       break;
00579   } //switch
00580 
00581   return NS_OK;
00582 
00583 }
00584 #endif