michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsLookAndFeel.h" michael@0: #include michael@0: #include michael@0: #include "nsStyleConsts.h" michael@0: #include "nsUXThemeData.h" michael@0: #include "nsUXThemeConstants.h" michael@0: #include "gfxFont.h" michael@0: #include "gfxWindowsPlatform.h" michael@0: #include "mozilla/Telemetry.h" michael@0: #include "mozilla/WindowsVersion.h" michael@0: #include "gfxFontConstants.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::widget; michael@0: michael@0: //static michael@0: LookAndFeel::OperatingSystemVersion michael@0: nsLookAndFeel::GetOperatingSystemVersion() michael@0: { michael@0: static OperatingSystemVersion version = eOperatingSystemVersion_Unknown; michael@0: michael@0: if (version != eOperatingSystemVersion_Unknown) { michael@0: return version; michael@0: } michael@0: michael@0: if (IsWin8OrLater()) { michael@0: version = eOperatingSystemVersion_Windows8; michael@0: } else if (IsWin7OrLater()) { michael@0: version = eOperatingSystemVersion_Windows7; michael@0: } else if (IsVistaOrLater()) { michael@0: version = eOperatingSystemVersion_WindowsVista; michael@0: } else { michael@0: version = eOperatingSystemVersion_WindowsXP; michael@0: } michael@0: michael@0: return version; michael@0: } michael@0: michael@0: static nsresult GetColorFromTheme(nsUXThemeClass cls, michael@0: int32_t aPart, michael@0: int32_t aState, michael@0: int32_t aPropId, michael@0: nscolor &aColor) michael@0: { michael@0: COLORREF color; michael@0: HRESULT hr = GetThemeColor(nsUXThemeData::GetTheme(cls), aPart, aState, aPropId, &color); michael@0: if (hr == S_OK) michael@0: { michael@0: aColor = COLOREF_2_NSRGB(color); michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: static int32_t GetSystemParam(long flag, int32_t def) michael@0: { michael@0: DWORD value; michael@0: return ::SystemParametersInfo(flag, 0, &value, 0) ? value : def; michael@0: } michael@0: michael@0: namespace mozilla { michael@0: namespace widget { michael@0: // This is in use here and in dom/events/TouchEvent.cpp michael@0: int32_t IsTouchDeviceSupportPresent() michael@0: { michael@0: int32_t touchCapabilities; michael@0: touchCapabilities = ::GetSystemMetrics(SM_DIGITIZER); michael@0: return ((touchCapabilities & NID_READY) && michael@0: (touchCapabilities & (NID_EXTERNAL_TOUCH | NID_INTEGRATED_TOUCH))); michael@0: } michael@0: } } michael@0: michael@0: nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel() michael@0: { michael@0: mozilla::Telemetry::Accumulate(mozilla::Telemetry::TOUCH_ENABLED_DEVICE, michael@0: IsTouchDeviceSupportPresent()); michael@0: } michael@0: michael@0: nsLookAndFeel::~nsLookAndFeel() michael@0: { michael@0: } michael@0: michael@0: nsresult michael@0: nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor) michael@0: { michael@0: nsresult res = NS_OK; michael@0: michael@0: int idx; michael@0: switch (aID) { michael@0: case eColorID_WindowBackground: michael@0: idx = COLOR_WINDOW; michael@0: break; michael@0: case eColorID_WindowForeground: michael@0: idx = COLOR_WINDOWTEXT; michael@0: break; michael@0: case eColorID_WidgetBackground: michael@0: idx = COLOR_BTNFACE; michael@0: break; michael@0: case eColorID_WidgetForeground: michael@0: idx = COLOR_BTNTEXT; michael@0: break; michael@0: case eColorID_WidgetSelectBackground: michael@0: idx = COLOR_HIGHLIGHT; michael@0: break; michael@0: case eColorID_WidgetSelectForeground: michael@0: idx = COLOR_HIGHLIGHTTEXT; michael@0: break; michael@0: case eColorID_Widget3DHighlight: michael@0: idx = COLOR_BTNHIGHLIGHT; michael@0: break; michael@0: case eColorID_Widget3DShadow: michael@0: idx = COLOR_BTNSHADOW; michael@0: break; michael@0: case eColorID_TextBackground: michael@0: idx = COLOR_WINDOW; michael@0: break; michael@0: case eColorID_TextForeground: michael@0: idx = COLOR_WINDOWTEXT; michael@0: break; michael@0: case eColorID_TextSelectBackground: michael@0: case eColorID_IMESelectedRawTextBackground: michael@0: case eColorID_IMESelectedConvertedTextBackground: michael@0: idx = COLOR_HIGHLIGHT; michael@0: break; michael@0: case eColorID_TextSelectForeground: michael@0: case eColorID_IMESelectedRawTextForeground: michael@0: case eColorID_IMESelectedConvertedTextForeground: michael@0: idx = COLOR_HIGHLIGHTTEXT; michael@0: break; michael@0: case eColorID_IMERawInputBackground: michael@0: case eColorID_IMEConvertedTextBackground: michael@0: aColor = NS_TRANSPARENT; michael@0: return NS_OK; michael@0: case eColorID_IMERawInputForeground: michael@0: case eColorID_IMEConvertedTextForeground: michael@0: aColor = NS_SAME_AS_FOREGROUND_COLOR; michael@0: return NS_OK; michael@0: case eColorID_IMERawInputUnderline: michael@0: case eColorID_IMEConvertedTextUnderline: michael@0: aColor = NS_SAME_AS_FOREGROUND_COLOR; michael@0: return NS_OK; michael@0: case eColorID_IMESelectedRawTextUnderline: michael@0: case eColorID_IMESelectedConvertedTextUnderline: michael@0: aColor = NS_TRANSPARENT; michael@0: return NS_OK; michael@0: case eColorID_SpellCheckerUnderline: michael@0: aColor = NS_RGB(0xff, 0, 0); michael@0: return NS_OK; michael@0: michael@0: // New CSS 2 Color definitions michael@0: case eColorID_activeborder: michael@0: idx = COLOR_ACTIVEBORDER; michael@0: break; michael@0: case eColorID_activecaption: michael@0: idx = COLOR_ACTIVECAPTION; michael@0: break; michael@0: case eColorID_appworkspace: michael@0: idx = COLOR_APPWORKSPACE; michael@0: break; michael@0: case eColorID_background: michael@0: idx = COLOR_BACKGROUND; michael@0: break; michael@0: case eColorID_buttonface: michael@0: case eColorID__moz_buttonhoverface: michael@0: idx = COLOR_BTNFACE; michael@0: break; michael@0: case eColorID_buttonhighlight: michael@0: idx = COLOR_BTNHIGHLIGHT; michael@0: break; michael@0: case eColorID_buttonshadow: michael@0: idx = COLOR_BTNSHADOW; michael@0: break; michael@0: case eColorID_buttontext: michael@0: case eColorID__moz_buttonhovertext: michael@0: idx = COLOR_BTNTEXT; michael@0: break; michael@0: case eColorID_captiontext: michael@0: idx = COLOR_CAPTIONTEXT; michael@0: break; michael@0: case eColorID_graytext: michael@0: idx = COLOR_GRAYTEXT; michael@0: break; michael@0: case eColorID_highlight: michael@0: case eColorID__moz_html_cellhighlight: michael@0: case eColorID__moz_menuhover: michael@0: idx = COLOR_HIGHLIGHT; michael@0: break; michael@0: case eColorID__moz_menubarhovertext: michael@0: if (!IsVistaOrLater() || !IsAppThemed()) michael@0: { michael@0: idx = nsUXThemeData::sFlatMenus ? michael@0: COLOR_HIGHLIGHTTEXT : michael@0: COLOR_MENUTEXT; michael@0: break; michael@0: } michael@0: // Fall through michael@0: case eColorID__moz_menuhovertext: michael@0: if (IsVistaOrLater() && IsAppThemed()) michael@0: { michael@0: res = ::GetColorFromTheme(eUXMenu, michael@0: MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR, aColor); michael@0: if (NS_SUCCEEDED(res)) michael@0: return res; michael@0: // fall through to highlight case michael@0: } michael@0: case eColorID_highlighttext: michael@0: case eColorID__moz_html_cellhighlighttext: michael@0: idx = COLOR_HIGHLIGHTTEXT; michael@0: break; michael@0: case eColorID_inactiveborder: michael@0: idx = COLOR_INACTIVEBORDER; michael@0: break; michael@0: case eColorID_inactivecaption: michael@0: idx = COLOR_INACTIVECAPTION; michael@0: break; michael@0: case eColorID_inactivecaptiontext: michael@0: idx = COLOR_INACTIVECAPTIONTEXT; michael@0: break; michael@0: case eColorID_infobackground: michael@0: idx = COLOR_INFOBK; michael@0: break; michael@0: case eColorID_infotext: michael@0: idx = COLOR_INFOTEXT; michael@0: break; michael@0: case eColorID_menu: michael@0: idx = COLOR_MENU; michael@0: break; michael@0: case eColorID_menutext: michael@0: case eColorID__moz_menubartext: michael@0: idx = COLOR_MENUTEXT; michael@0: break; michael@0: case eColorID_scrollbar: michael@0: idx = COLOR_SCROLLBAR; michael@0: break; michael@0: case eColorID_threeddarkshadow: michael@0: idx = COLOR_3DDKSHADOW; michael@0: break; michael@0: case eColorID_threedface: michael@0: idx = COLOR_3DFACE; michael@0: break; michael@0: case eColorID_threedhighlight: michael@0: idx = COLOR_3DHIGHLIGHT; michael@0: break; michael@0: case eColorID_threedlightshadow: michael@0: idx = COLOR_3DLIGHT; michael@0: break; michael@0: case eColorID_threedshadow: michael@0: idx = COLOR_3DSHADOW; michael@0: break; michael@0: case eColorID_window: michael@0: idx = COLOR_WINDOW; michael@0: break; michael@0: case eColorID_windowframe: michael@0: idx = COLOR_WINDOWFRAME; michael@0: break; michael@0: case eColorID_windowtext: michael@0: idx = COLOR_WINDOWTEXT; michael@0: break; michael@0: case eColorID__moz_eventreerow: michael@0: case eColorID__moz_oddtreerow: michael@0: case eColorID__moz_field: michael@0: case eColorID__moz_combobox: michael@0: idx = COLOR_WINDOW; michael@0: break; michael@0: case eColorID__moz_fieldtext: michael@0: case eColorID__moz_comboboxtext: michael@0: idx = COLOR_WINDOWTEXT; michael@0: break; michael@0: case eColorID__moz_dialog: michael@0: case eColorID__moz_cellhighlight: michael@0: idx = COLOR_3DFACE; michael@0: break; michael@0: case eColorID__moz_win_mediatext: michael@0: if (IsVistaOrLater() && IsAppThemed()) { michael@0: res = ::GetColorFromTheme(eUXMediaToolbar, michael@0: TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor); michael@0: if (NS_SUCCEEDED(res)) michael@0: return res; michael@0: } michael@0: // if we've gotten here just return -moz-dialogtext instead michael@0: idx = COLOR_WINDOWTEXT; michael@0: break; michael@0: case eColorID__moz_win_communicationstext: michael@0: if (IsVistaOrLater() && IsAppThemed()) michael@0: { michael@0: res = ::GetColorFromTheme(eUXCommunicationsToolbar, michael@0: TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor); michael@0: if (NS_SUCCEEDED(res)) michael@0: return res; michael@0: } michael@0: // if we've gotten here just return -moz-dialogtext instead michael@0: idx = COLOR_WINDOWTEXT; michael@0: break; michael@0: case eColorID__moz_dialogtext: michael@0: case eColorID__moz_cellhighlighttext: michael@0: idx = COLOR_WINDOWTEXT; michael@0: break; michael@0: case eColorID__moz_dragtargetzone: michael@0: idx = COLOR_HIGHLIGHTTEXT; michael@0: break; michael@0: case eColorID__moz_buttondefault: michael@0: idx = COLOR_3DDKSHADOW; michael@0: break; michael@0: case eColorID__moz_nativehyperlinktext: michael@0: idx = COLOR_HOTLIGHT; michael@0: break; michael@0: default: michael@0: idx = COLOR_WINDOW; michael@0: break; michael@0: } michael@0: michael@0: DWORD color = ::GetSysColor(idx); michael@0: aColor = COLOREF_2_NSRGB(color); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: nsresult michael@0: nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) michael@0: { michael@0: nsresult res = nsXPLookAndFeel::GetIntImpl(aID, aResult); michael@0: if (NS_SUCCEEDED(res)) michael@0: return res; michael@0: res = NS_OK; michael@0: michael@0: switch (aID) { michael@0: case eIntID_CaretBlinkTime: michael@0: aResult = (int32_t)::GetCaretBlinkTime(); michael@0: break; michael@0: case eIntID_CaretWidth: michael@0: aResult = 1; michael@0: break; michael@0: case eIntID_ShowCaretDuringSelection: michael@0: aResult = 0; michael@0: break; michael@0: case eIntID_SelectTextfieldsOnKeyFocus: michael@0: // Select textfield content when focused by kbd michael@0: // used by EventStateManager::sTextfieldSelectModel michael@0: aResult = 1; michael@0: break; michael@0: case eIntID_SubmenuDelay: michael@0: // This will default to the Windows' default michael@0: // (400ms) on error. michael@0: aResult = GetSystemParam(SPI_GETMENUSHOWDELAY, 400); michael@0: break; michael@0: case eIntID_TooltipDelay: michael@0: aResult = 500; michael@0: break; michael@0: case eIntID_MenusCanOverlapOSBar: michael@0: // we want XUL popups to be able to overlap the task bar. michael@0: aResult = 1; michael@0: break; michael@0: case eIntID_DragThresholdX: michael@0: // The system metric is the number of pixels at which a drag should michael@0: // start. Our look and feel metric is the number of pixels you can michael@0: // move before starting a drag, so subtract 1. michael@0: michael@0: aResult = ::GetSystemMetrics(SM_CXDRAG) - 1; michael@0: break; michael@0: case eIntID_DragThresholdY: michael@0: aResult = ::GetSystemMetrics(SM_CYDRAG) - 1; michael@0: break; michael@0: case eIntID_UseAccessibilityTheme: michael@0: // High contrast is a misnomer under Win32 -- any theme can be used with it, michael@0: // e.g. normal contrast with large fonts, low contrast, etc. michael@0: // The high contrast flag really means -- use this theme and don't override it. michael@0: aResult = nsUXThemeData::IsHighContrastOn(); michael@0: break; michael@0: case eIntID_ScrollArrowStyle: michael@0: aResult = eScrollArrowStyle_Single; michael@0: break; michael@0: case eIntID_ScrollSliderStyle: michael@0: aResult = eScrollThumbStyle_Proportional; michael@0: break; michael@0: case eIntID_TreeOpenDelay: michael@0: aResult = 1000; michael@0: break; michael@0: case eIntID_TreeCloseDelay: michael@0: aResult = 0; michael@0: break; michael@0: case eIntID_TreeLazyScrollDelay: michael@0: aResult = 150; michael@0: break; michael@0: case eIntID_TreeScrollDelay: michael@0: aResult = 100; michael@0: break; michael@0: case eIntID_TreeScrollLinesMax: michael@0: aResult = 3; michael@0: break; michael@0: case eIntID_WindowsClassic: michael@0: aResult = !IsAppThemed(); michael@0: break; michael@0: case eIntID_TouchEnabled: michael@0: aResult = IsTouchDeviceSupportPresent(); michael@0: break; michael@0: case eIntID_WindowsDefaultTheme: michael@0: aResult = nsUXThemeData::IsDefaultWindowTheme(); michael@0: break; michael@0: case eIntID_WindowsThemeIdentifier: michael@0: aResult = nsUXThemeData::GetNativeThemeId(); michael@0: break; michael@0: michael@0: case eIntID_OperatingSystemVersionIdentifier: michael@0: { michael@0: aResult = GetOperatingSystemVersion(); michael@0: break; michael@0: } michael@0: michael@0: case eIntID_MacGraphiteTheme: michael@0: case eIntID_MacLionTheme: michael@0: aResult = 0; michael@0: res = NS_ERROR_NOT_IMPLEMENTED; michael@0: break; michael@0: case eIntID_DWMCompositor: michael@0: aResult = nsUXThemeData::CheckForCompositor(); michael@0: break; michael@0: case eIntID_WindowsGlass: michael@0: // Aero Glass is only available prior to Windows 8 when DWM is used. michael@0: aResult = (nsUXThemeData::CheckForCompositor() && !IsWin8OrLater()); michael@0: break; michael@0: case eIntID_AlertNotificationOrigin: michael@0: aResult = 0; michael@0: { michael@0: // Get task bar window handle michael@0: HWND shellWindow = FindWindowW(L"Shell_TrayWnd", nullptr); michael@0: michael@0: if (shellWindow != nullptr) michael@0: { michael@0: // Determine position michael@0: APPBARDATA appBarData; michael@0: appBarData.hWnd = shellWindow; michael@0: appBarData.cbSize = sizeof(appBarData); michael@0: if (SHAppBarMessage(ABM_GETTASKBARPOS, &appBarData)) michael@0: { michael@0: // Set alert origin as a bit field - see LookAndFeel.h michael@0: // 0 represents bottom right, sliding vertically. michael@0: switch(appBarData.uEdge) michael@0: { michael@0: case ABE_LEFT: michael@0: aResult = NS_ALERT_HORIZONTAL | NS_ALERT_LEFT; michael@0: break; michael@0: case ABE_RIGHT: michael@0: aResult = NS_ALERT_HORIZONTAL; michael@0: break; michael@0: case ABE_TOP: michael@0: aResult = NS_ALERT_TOP; michael@0: // fall through for the right-to-left handling. michael@0: case ABE_BOTTOM: michael@0: // If the task bar is right-to-left, michael@0: // move the origin to the left michael@0: if (::GetWindowLong(shellWindow, GWL_EXSTYLE) & michael@0: WS_EX_LAYOUTRTL) michael@0: aResult |= NS_ALERT_LEFT; michael@0: break; michael@0: } michael@0: } michael@0: } michael@0: } michael@0: break; michael@0: case eIntID_IMERawInputUnderlineStyle: michael@0: case eIntID_IMEConvertedTextUnderlineStyle: michael@0: aResult = NS_STYLE_TEXT_DECORATION_STYLE_DASHED; michael@0: break; michael@0: case eIntID_IMESelectedRawTextUnderlineStyle: michael@0: case eIntID_IMESelectedConvertedTextUnderline: michael@0: aResult = NS_STYLE_TEXT_DECORATION_STYLE_NONE; michael@0: break; michael@0: case eIntID_SpellCheckerUnderlineStyle: michael@0: aResult = NS_STYLE_TEXT_DECORATION_STYLE_WAVY; michael@0: break; michael@0: case eIntID_ScrollbarButtonAutoRepeatBehavior: michael@0: aResult = 0; michael@0: break; michael@0: case eIntID_SwipeAnimationEnabled: michael@0: aResult = 0; michael@0: break; michael@0: case eIntID_ColorPickerAvailable: michael@0: // We don't have a color picker implemented on Metro yet (bug 895464) michael@0: aResult = (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Metro); michael@0: break; michael@0: case eIntID_UseOverlayScrollbars: michael@0: aResult = (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro); michael@0: break; michael@0: case eIntID_AllowOverlayScrollbarsOverlap: michael@0: aResult = 0; michael@0: break; michael@0: case eIntID_ScrollbarDisplayOnMouseMove: michael@0: aResult = 1; michael@0: break; michael@0: case eIntID_ScrollbarFadeBeginDelay: michael@0: aResult = 2500; michael@0: break; michael@0: case eIntID_ScrollbarFadeDuration: michael@0: aResult = 350; michael@0: break; michael@0: default: michael@0: aResult = 0; michael@0: res = NS_ERROR_FAILURE; michael@0: } michael@0: return res; michael@0: } michael@0: michael@0: nsresult michael@0: nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult) michael@0: { michael@0: nsresult res = nsXPLookAndFeel::GetFloatImpl(aID, aResult); michael@0: if (NS_SUCCEEDED(res)) michael@0: return res; michael@0: res = NS_OK; michael@0: michael@0: switch (aID) { michael@0: case eFloatID_IMEUnderlineRelativeSize: michael@0: aResult = 1.0f; michael@0: break; michael@0: case eFloatID_SpellCheckerUnderlineRelativeSize: michael@0: aResult = 1.0f; michael@0: break; michael@0: default: michael@0: aResult = -1.0; michael@0: res = NS_ERROR_FAILURE; michael@0: } michael@0: return res; michael@0: } michael@0: michael@0: static bool michael@0: GetSysFontInfo(HDC aHDC, LookAndFeel::FontID anID, michael@0: nsString &aFontName, michael@0: gfxFontStyle &aFontStyle) michael@0: { michael@0: LOGFONTW* ptrLogFont = nullptr; michael@0: LOGFONTW logFont; michael@0: NONCLIENTMETRICSW ncm; michael@0: HGDIOBJ hGDI; michael@0: char16_t name[LF_FACESIZE]; michael@0: michael@0: // Depending on which stock font we want, there are three different michael@0: // places we might have to look it up. michael@0: switch (anID) { michael@0: case LookAndFeel::eFont_Icon: michael@0: if (!::SystemParametersInfoW(SPI_GETICONTITLELOGFONT, michael@0: sizeof(logFont), (PVOID)&logFont, 0)) michael@0: return false; michael@0: michael@0: ptrLogFont = &logFont; michael@0: break; michael@0: michael@0: case LookAndFeel::eFont_Menu: michael@0: case LookAndFeel::eFont_MessageBox: michael@0: case LookAndFeel::eFont_SmallCaption: michael@0: case LookAndFeel::eFont_StatusBar: michael@0: case LookAndFeel::eFont_Tooltips: michael@0: ncm.cbSize = sizeof(NONCLIENTMETRICSW); michael@0: if (!::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, michael@0: sizeof(ncm), (PVOID)&ncm, 0)) michael@0: return false; michael@0: michael@0: switch (anID) { michael@0: case LookAndFeel::eFont_Menu: michael@0: ptrLogFont = &ncm.lfMenuFont; michael@0: break; michael@0: case LookAndFeel::eFont_MessageBox: michael@0: ptrLogFont = &ncm.lfMessageFont; michael@0: break; michael@0: case LookAndFeel::eFont_SmallCaption: michael@0: ptrLogFont = &ncm.lfSmCaptionFont; michael@0: break; michael@0: case LookAndFeel::eFont_StatusBar: michael@0: case LookAndFeel::eFont_Tooltips: michael@0: ptrLogFont = &ncm.lfStatusFont; michael@0: break; michael@0: } michael@0: break; michael@0: michael@0: case LookAndFeel::eFont_Widget: michael@0: case LookAndFeel::eFont_Window: // css3 michael@0: case LookAndFeel::eFont_Document: michael@0: case LookAndFeel::eFont_Workspace: michael@0: case LookAndFeel::eFont_Desktop: michael@0: case LookAndFeel::eFont_Info: michael@0: case LookAndFeel::eFont_Dialog: michael@0: case LookAndFeel::eFont_Button: michael@0: case LookAndFeel::eFont_PullDownMenu: michael@0: case LookAndFeel::eFont_List: michael@0: case LookAndFeel::eFont_Field: michael@0: case LookAndFeel::eFont_Caption: michael@0: hGDI = ::GetStockObject(DEFAULT_GUI_FONT); michael@0: if (!hGDI) michael@0: return false; michael@0: michael@0: if (::GetObjectW(hGDI, sizeof(logFont), &logFont) <= 0) michael@0: return false; michael@0: michael@0: ptrLogFont = &logFont; michael@0: break; michael@0: } michael@0: michael@0: // Get scaling factor from physical to logical pixels michael@0: float pixelScale = 1.0f / gfxWindowsPlatform::GetPlatform()->GetDPIScale(); michael@0: michael@0: // The lfHeight is in pixels, and it needs to be adjusted for the michael@0: // device it will be displayed on. michael@0: // Screens and Printers will differ in DPI michael@0: // michael@0: // So this accounts for the difference in the DeviceContexts michael@0: // The pixelScale will typically be 1.0 for the screen michael@0: // (though larger for hi-dpi screens where the Windows resolution michael@0: // scale factor is 125% or 150% or even more), and could be michael@0: // any value when going to a printer, for example pixelScale is michael@0: // 6.25 when going to a 600dpi printer. michael@0: float pixelHeight = -ptrLogFont->lfHeight; michael@0: if (pixelHeight < 0) { michael@0: HFONT hFont = ::CreateFontIndirectW(ptrLogFont); michael@0: if (!hFont) michael@0: return false; michael@0: HGDIOBJ hObject = ::SelectObject(aHDC, hFont); michael@0: TEXTMETRIC tm; michael@0: ::GetTextMetrics(aHDC, &tm); michael@0: ::SelectObject(aHDC, hObject); michael@0: ::DeleteObject(hFont); michael@0: pixelHeight = tm.tmAscent; michael@0: } michael@0: pixelHeight *= pixelScale; michael@0: michael@0: // we have problem on Simplified Chinese system because the system michael@0: // report the default font size is 8 points. but if we use 8, the text michael@0: // display very ugly. force it to be at 9 points (12 pixels) on that michael@0: // system (cp936), but leave other sizes alone. michael@0: if (pixelHeight < 12 && ::GetACP() == 936) michael@0: pixelHeight = 12; michael@0: michael@0: aFontStyle.size = pixelHeight; michael@0: michael@0: // FIXME: What about oblique? michael@0: aFontStyle.style = michael@0: (ptrLogFont->lfItalic) ? NS_FONT_STYLE_ITALIC : NS_FONT_STYLE_NORMAL; michael@0: michael@0: // FIXME: Other weights? michael@0: aFontStyle.weight = michael@0: (ptrLogFont->lfWeight == FW_BOLD ? michael@0: NS_FONT_WEIGHT_BOLD : NS_FONT_WEIGHT_NORMAL); michael@0: michael@0: // FIXME: Set aFontStyle->stretch correctly! michael@0: aFontStyle.stretch = NS_FONT_STRETCH_NORMAL; michael@0: michael@0: aFontStyle.systemFont = true; michael@0: michael@0: name[0] = 0; michael@0: memcpy(name, ptrLogFont->lfFaceName, LF_FACESIZE*sizeof(char16_t)); michael@0: aFontName = name; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: nsLookAndFeel::GetFontImpl(FontID anID, nsString &aFontName, michael@0: gfxFontStyle &aFontStyle, michael@0: float aDevPixPerCSSPixel) michael@0: { michael@0: HDC tdc = GetDC(nullptr); michael@0: bool status = GetSysFontInfo(tdc, anID, aFontName, aFontStyle); michael@0: ReleaseDC(nullptr, tdc); michael@0: // now convert the logical font size from GetSysFontInfo into device pixels for layout michael@0: aFontStyle.size *= aDevPixPerCSSPixel; michael@0: return status; michael@0: } michael@0: michael@0: /* virtual */ michael@0: char16_t michael@0: nsLookAndFeel::GetPasswordCharacterImpl() michael@0: { michael@0: #define UNICODE_BLACK_CIRCLE_CHAR 0x25cf michael@0: return UNICODE_BLACK_CIRCLE_CHAR; michael@0: }