1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsLookAndFeel.h"
10 #include "nsStyleConsts.h"
11 #include "nsUXThemeData.h"
12 #include "nsUXThemeConstants.h"
13 #include "nsWindowsHelpers.h"
15 #include "WindowsUIUtils.h"
16 #include "mozilla/FontPropertyTypes.h"
17 #include "mozilla/Telemetry.h"
18 #include "mozilla/WindowsVersion.h"
19 #include "gfxFontConstants.h"
20 #include "gfxWindowsPlatform.h"
22 using namespace mozilla
;
23 using namespace mozilla::widget
;
25 static Maybe
<nscolor
> GetColorFromTheme(nsUXThemeClass cls
, int32_t aPart
,
26 int32_t aState
, int32_t aPropId
) {
28 HRESULT hr
= GetThemeColor(nsUXThemeData::GetTheme(cls
), aPart
, aState
,
31 return Some(COLOREF_2_NSRGB(color
));
36 static int32_t GetSystemParam(long flag
, int32_t def
) {
38 return ::SystemParametersInfo(flag
, 0, &value
, 0) ? value
: def
;
41 static nsresult
SystemWantsDarkTheme(int32_t& darkThemeEnabled
) {
42 if (!IsWin10OrLater()) {
48 nsCOMPtr
<nsIWindowsRegKey
> personalizeKey
=
49 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv
);
50 if (NS_WARN_IF(NS_FAILED(rv
))) {
54 rv
= personalizeKey
->Open(
55 nsIWindowsRegKey::ROOT_KEY_CURRENT_USER
,
57 u
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"),
58 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
63 uint32_t lightThemeEnabled
;
65 personalizeKey
->ReadIntValue(u
"AppsUseLightTheme"_ns
, &lightThemeEnabled
);
66 if (NS_SUCCEEDED(rv
)) {
67 darkThemeEnabled
= !lightThemeEnabled
;
73 nsLookAndFeel::nsLookAndFeel() {
74 mozilla::Telemetry::Accumulate(mozilla::Telemetry::TOUCH_ENABLED_DEVICE
,
75 WinUtils::IsTouchDeviceSupportPresent());
78 nsLookAndFeel::~nsLookAndFeel() = default;
80 void nsLookAndFeel::NativeInit() { EnsureInit(); }
83 void nsLookAndFeel::RefreshImpl() {
84 mInitialized
= false; // Fetch system colors next time they're used.
85 nsXPLookAndFeel::RefreshImpl();
88 static bool UseNonNativeMenuColors(ColorScheme aScheme
) {
89 if (!LookAndFeel::WindowsNonNativeMenusEnabled()) {
92 return LookAndFeel::GetInt(LookAndFeel::IntID::WindowsDefaultTheme
) ||
93 aScheme
== ColorScheme::Dark
;
96 nsresult
nsLookAndFeel::NativeGetColor(ColorID aID
, ColorScheme aScheme
,
100 auto IsHighlightColor
= [&] {
102 case ColorID::MozMenuhover
:
103 return !UseNonNativeMenuColors(aScheme
);
104 case ColorID::Highlight
:
105 case ColorID::Selecteditem
:
106 // We prefer the generic dark selection color if we don't have an
108 return aScheme
!= ColorScheme::Dark
|| mDarkHighlight
;
109 case ColorID::IMESelectedRawTextBackground
:
110 case ColorID::IMESelectedConvertedTextBackground
:
117 auto IsHighlightTextColor
= [&] {
119 case ColorID::MozMenubarhovertext
:
120 if (UseNonNativeMenuColors(aScheme
)) {
123 if (!nsUXThemeData::IsAppThemed()) {
124 return nsUXThemeData::AreFlatMenusEnabled();
127 case ColorID::MozMenuhovertext
:
128 if (UseNonNativeMenuColors(aScheme
)) {
131 return !mColorMenuHoverText
;
132 case ColorID::Highlighttext
:
133 case ColorID::Selecteditemtext
:
134 // We prefer the generic dark selection color if we don't have an
136 return aScheme
!= ColorScheme::Dark
|| mDarkHighlightText
;
137 case ColorID::IMESelectedRawTextForeground
:
138 case ColorID::IMESelectedConvertedTextForeground
:
139 case ColorID::MozDragtargetzone
:
146 if (IsHighlightColor()) {
147 if (aScheme
== ColorScheme::Dark
&& mDarkHighlight
) {
148 aColor
= *mDarkHighlight
;
150 aColor
= GetColorForSysColorIndex(COLOR_HIGHLIGHT
);
155 if (IsHighlightTextColor()) {
156 if (aScheme
== ColorScheme::Dark
&& mDarkHighlightText
) {
157 aColor
= *mDarkHighlightText
;
159 aColor
= GetColorForSysColorIndex(COLOR_HIGHLIGHTTEXT
);
164 if (aScheme
== ColorScheme::Dark
) {
165 if (auto color
= GenericDarkColor(aID
)) {
171 static constexpr auto kNonNativeMenuText
= NS_RGB(0x15, 0x14, 0x1a);
172 nsresult res
= NS_OK
;
175 case ColorID::IMERawInputBackground
:
176 case ColorID::IMEConvertedTextBackground
:
177 aColor
= NS_TRANSPARENT
;
179 case ColorID::IMERawInputForeground
:
180 case ColorID::IMEConvertedTextForeground
:
181 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
183 case ColorID::IMERawInputUnderline
:
184 case ColorID::IMEConvertedTextUnderline
:
185 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
187 case ColorID::IMESelectedRawTextUnderline
:
188 case ColorID::IMESelectedConvertedTextUnderline
:
189 aColor
= NS_TRANSPARENT
;
192 // New CSS 2 Color definitions
193 case ColorID::Activeborder
:
194 idx
= COLOR_ACTIVEBORDER
;
196 case ColorID::Activecaption
:
197 idx
= COLOR_ACTIVECAPTION
;
199 case ColorID::Appworkspace
:
200 idx
= COLOR_APPWORKSPACE
;
202 case ColorID::Background
:
203 idx
= COLOR_BACKGROUND
;
205 case ColorID::Buttonface
:
206 case ColorID::MozButtonhoverface
:
207 case ColorID::MozButtonactiveface
:
208 case ColorID::MozButtondisabledface
:
211 case ColorID::Buttonhighlight
:
212 idx
= COLOR_BTNHIGHLIGHT
;
214 case ColorID::Buttonshadow
:
215 idx
= COLOR_BTNSHADOW
;
217 case ColorID::Buttontext
:
218 case ColorID::MozButtonhovertext
:
219 case ColorID::MozButtonactivetext
:
222 case ColorID::Captiontext
:
223 idx
= COLOR_CAPTIONTEXT
;
225 case ColorID::MozCellhighlighttext
:
226 aColor
= NS_RGB(0, 0, 0);
228 case ColorID::MozCellhighlight
:
229 aColor
= NS_RGB(206, 206, 206);
231 case ColorID::Graytext
:
232 idx
= COLOR_GRAYTEXT
;
234 case ColorID::MozMenubarhovertext
:
235 if (UseNonNativeMenuColors(aScheme
)) {
236 aColor
= kNonNativeMenuText
;
239 if (!nsUXThemeData::IsAppThemed()) {
240 idx
= COLOR_MENUTEXT
;
244 case ColorID::MozMenuhovertext
:
245 if (UseNonNativeMenuColors(aScheme
)) {
246 aColor
= kNonNativeMenuText
;
249 if (mColorMenuHoverText
) {
250 aColor
= *mColorMenuHoverText
;
253 idx
= COLOR_HIGHLIGHTTEXT
;
255 case ColorID::MozMenuhover
:
256 MOZ_ASSERT(UseNonNativeMenuColors(aScheme
));
257 aColor
= NS_RGB(0xe0, 0xe0, 0xe6);
259 case ColorID::MozMenuhoverdisabled
:
260 if (UseNonNativeMenuColors(aScheme
)) {
261 aColor
= NS_RGB(0xf0, 0xf0, 0xf3);
264 aColor
= NS_TRANSPARENT
;
266 case ColorID::Inactiveborder
:
267 idx
= COLOR_INACTIVEBORDER
;
269 case ColorID::Inactivecaption
:
270 idx
= COLOR_INACTIVECAPTION
;
272 case ColorID::Inactivecaptiontext
:
273 idx
= COLOR_INACTIVECAPTIONTEXT
;
275 case ColorID::Infobackground
:
278 case ColorID::Infotext
:
279 idx
= COLOR_INFOTEXT
;
282 if (UseNonNativeMenuColors(aScheme
)) {
283 aColor
= NS_RGB(0xf9, 0xf9, 0xfb);
288 case ColorID::Menutext
:
289 case ColorID::MozMenubartext
:
290 if (UseNonNativeMenuColors(aScheme
)) {
291 aColor
= kNonNativeMenuText
;
294 idx
= COLOR_MENUTEXT
;
296 case ColorID::Scrollbar
:
297 idx
= COLOR_SCROLLBAR
;
299 case ColorID::Threeddarkshadow
:
300 idx
= COLOR_3DDKSHADOW
;
302 case ColorID::Threedface
:
305 case ColorID::Threedhighlight
:
306 idx
= COLOR_3DHIGHLIGHT
;
308 case ColorID::Threedlightshadow
:
309 case ColorID::Buttonborder
:
310 case ColorID::MozDisabledfield
:
313 case ColorID::Threedshadow
:
314 idx
= COLOR_3DSHADOW
;
316 case ColorID::Window
:
319 case ColorID::Windowframe
:
320 idx
= COLOR_WINDOWFRAME
;
322 case ColorID::Windowtext
:
323 idx
= COLOR_WINDOWTEXT
;
325 case ColorID::MozEventreerow
:
326 case ColorID::MozOddtreerow
:
328 case ColorID::MozCombobox
:
331 case ColorID::Fieldtext
:
332 case ColorID::MozComboboxtext
:
333 idx
= COLOR_WINDOWTEXT
;
335 case ColorID::MozDialog
:
338 case ColorID::Accentcolor
:
340 aColor
= *mColorAccent
;
342 // Seems to be the default color (hardcoded because of bug 1065998)
343 aColor
= NS_RGB(0, 120, 215);
346 case ColorID::Accentcolortext
:
347 if (mColorAccentText
) {
348 aColor
= *mColorAccentText
;
350 aColor
= NS_RGB(255, 255, 255);
353 case ColorID::MozWinMediatext
:
354 if (mColorMediaText
) {
355 aColor
= *mColorMediaText
;
358 // if we've gotten here just return -moz-dialogtext instead
359 idx
= COLOR_WINDOWTEXT
;
361 case ColorID::MozWinCommunicationstext
:
362 if (mColorCommunicationsText
) {
363 aColor
= *mColorCommunicationsText
;
366 // if we've gotten here just return -moz-dialogtext instead
367 idx
= COLOR_WINDOWTEXT
;
369 case ColorID::MozDialogtext
:
370 case ColorID::MozColheadertext
:
371 case ColorID::MozColheaderhovertext
:
372 idx
= COLOR_WINDOWTEXT
;
374 case ColorID::MozButtondefault
:
375 idx
= COLOR_3DDKSHADOW
;
377 case ColorID::MozNativehyperlinktext
:
378 idx
= COLOR_HOTLIGHT
;
380 case ColorID::Marktext
:
382 case ColorID::SpellCheckerUnderline
:
383 aColor
= GetStandinForNativeColor(aID
, aScheme
);
387 res
= NS_ERROR_FAILURE
;
391 aColor
= GetColorForSysColorIndex(idx
);
396 nsresult
nsLookAndFeel::NativeGetInt(IntID aID
, int32_t& aResult
) {
398 nsresult res
= NS_OK
;
401 case IntID::ScrollButtonLeftMouseButtonAction
:
404 case IntID::ScrollButtonMiddleMouseButtonAction
:
405 case IntID::ScrollButtonRightMouseButtonAction
:
408 case IntID::CaretBlinkTime
:
409 aResult
= static_cast<int32_t>(::GetCaretBlinkTime());
411 case IntID::CaretBlinkCount
: {
412 int32_t timeout
= GetSystemParam(SPI_GETCARETTIMEOUT
, 5000);
413 auto blinkTime
= ::GetCaretBlinkTime();
414 if (timeout
<= 0 || blinkTime
<= 0) {
418 // 2 * blinkTime because this integer is a full blink cycle.
419 aResult
= std::ceil(float(timeout
) / (2.0f
* float(blinkTime
)));
423 case IntID::CaretWidth
:
426 case IntID::ShowCaretDuringSelection
:
429 case IntID::SelectTextfieldsOnKeyFocus
:
430 // Select textfield content when focused by kbd
431 // used by EventStateManager::sTextfieldSelectModel
434 case IntID::SubmenuDelay
:
435 // This will default to the Windows' default
437 aResult
= GetSystemParam(SPI_GETMENUSHOWDELAY
, 400);
439 case IntID::TooltipDelay
:
442 case IntID::MenusCanOverlapOSBar
:
443 // we want XUL popups to be able to overlap the task bar.
446 case IntID::DragThresholdX
:
447 // The system metric is the number of pixels at which a drag should
448 // start. Our look and feel metric is the number of pixels you can
449 // move before starting a drag, so subtract 1.
450 aResult
= ::GetSystemMetrics(SM_CXDRAG
) - 1;
452 case IntID::DragThresholdY
:
453 aResult
= ::GetSystemMetrics(SM_CYDRAG
) - 1;
455 case IntID::UseAccessibilityTheme
:
456 // High contrast is a misnomer under Win32 -- any theme can be used with
457 // it, e.g. normal contrast with large fonts, low contrast, etc. The high
458 // contrast flag really means -- use this theme and don't override it.
459 aResult
= nsUXThemeData::IsHighContrastOn();
461 case IntID::ScrollArrowStyle
:
462 aResult
= eScrollArrowStyle_Single
;
464 case IntID::TreeOpenDelay
:
467 case IntID::TreeCloseDelay
:
470 case IntID::TreeLazyScrollDelay
:
473 case IntID::TreeScrollDelay
:
476 case IntID::TreeScrollLinesMax
:
479 case IntID::WindowsClassic
:
480 aResult
= !nsUXThemeData::IsAppThemed();
482 case IntID::WindowsDefaultTheme
:
483 aResult
= nsUXThemeData::IsDefaultWindowTheme();
485 case IntID::ShowKeyboardCues
: {
487 ::SystemParametersInfoW(SPI_GETKEYBOARDCUES
, 0, &show
, 0);
491 case IntID::DWMCompositor
:
492 aResult
= gfxWindowsPlatform::GetPlatform()->DwmCompositionEnabled();
494 case IntID::WindowsAccentColorInTitlebar
: {
496 if (NS_WARN_IF(!mColorAccent
)) {
501 mDwmKey
= do_CreateInstance("@mozilla.org/windows-registry-key;1");
506 uint32_t colorPrevalence
;
507 nsresult rv
= mDwmKey
->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER
,
508 u
"SOFTWARE\\Microsoft\\Windows\\DWM"_ns
,
509 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
510 if (NS_WARN_IF(NS_FAILED(rv
))) {
514 // The ColorPrevalence value is set to 1 when the "Show color on title
515 // bar" setting in the Color section of Window's Personalization settings
517 aResult
= (NS_SUCCEEDED(mDwmKey
->ReadIntValue(u
"ColorPrevalence"_ns
,
518 &colorPrevalence
)) &&
519 colorPrevalence
== 1)
525 case IntID::WindowsGlass
:
526 // Aero Glass is only available prior to Windows 8 when DWM is used.
527 aResult
= (gfxWindowsPlatform::GetPlatform()->DwmCompositionEnabled() &&
530 case IntID::AlertNotificationOrigin
:
533 // Get task bar window handle
534 HWND shellWindow
= FindWindowW(L
"Shell_TrayWnd", nullptr);
536 if (shellWindow
!= nullptr) {
537 // Determine position
538 APPBARDATA appBarData
;
539 appBarData
.hWnd
= shellWindow
;
540 appBarData
.cbSize
= sizeof(appBarData
);
541 if (SHAppBarMessage(ABM_GETTASKBARPOS
, &appBarData
)) {
542 // Set alert origin as a bit field - see LookAndFeel.h
543 // 0 represents bottom right, sliding vertically.
544 switch (appBarData
.uEdge
) {
546 aResult
= NS_ALERT_HORIZONTAL
| NS_ALERT_LEFT
;
549 aResult
= NS_ALERT_HORIZONTAL
;
552 aResult
= NS_ALERT_TOP
;
555 // If the task bar is right-to-left,
556 // move the origin to the left
557 if (::GetWindowLong(shellWindow
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
)
558 aResult
|= NS_ALERT_LEFT
;
565 case IntID::IMERawInputUnderlineStyle
:
566 case IntID::IMEConvertedTextUnderlineStyle
:
567 aResult
= static_cast<int32_t>(StyleTextDecorationStyle::Dashed
);
569 case IntID::IMESelectedRawTextUnderlineStyle
:
570 case IntID::IMESelectedConvertedTextUnderline
:
571 aResult
= static_cast<int32_t>(StyleTextDecorationStyle::None
);
573 case IntID::SpellCheckerUnderlineStyle
:
574 aResult
= static_cast<int32_t>(StyleTextDecorationStyle::Wavy
);
576 case IntID::ScrollbarButtonAutoRepeatBehavior
:
579 case IntID::SwipeAnimationEnabled
:
580 // Forcibly enable the swipe animation on Windows. It doesn't matter on
581 // platforms where "Drag two fingers to scroll" isn't supported since on
582 // the platforms we will never generate any swipe gesture events.
585 case IntID::UseOverlayScrollbars
:
586 aResult
= WindowsUIUtils::ComputeOverlayScrollbars();
588 case IntID::AllowOverlayScrollbarsOverlap
:
591 case IntID::ScrollbarDisplayOnMouseMove
:
594 case IntID::ScrollbarFadeBeginDelay
:
597 case IntID::ScrollbarFadeDuration
:
600 case IntID::ContextMenuOffsetVertical
:
601 case IntID::ContextMenuOffsetHorizontal
:
604 case IntID::SystemUsesDarkTheme
:
605 res
= SystemWantsDarkTheme(aResult
);
607 case IntID::SystemScrollbarSize
:
608 aResult
= std::max(WinUtils::GetSystemMetricsForDpi(SM_CXVSCROLL
, 96),
609 WinUtils::GetSystemMetricsForDpi(SM_CXHSCROLL
, 96));
611 case IntID::PrefersReducedMotion
: {
613 ::SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION
, 0, &enable
, 0);
617 case IntID::PrimaryPointerCapabilities
: {
618 aResult
= static_cast<int32_t>(
619 widget::WinUtils::GetPrimaryPointerCapabilities());
622 case IntID::AllPointerCapabilities
: {
624 static_cast<int32_t>(widget::WinUtils::GetAllPointerCapabilities());
627 case IntID::TouchDeviceSupportPresent
:
628 aResult
= WinUtils::IsTouchDeviceSupportPresent() ? 1 : 0;
630 case IntID::PanelAnimations
:
635 res
= NS_ERROR_FAILURE
;
640 nsresult
nsLookAndFeel::NativeGetFloat(FloatID aID
, float& aResult
) {
641 nsresult res
= NS_OK
;
644 case FloatID::IMEUnderlineRelativeSize
:
647 case FloatID::SpellCheckerUnderlineRelativeSize
:
650 case FloatID::TextScaleFactor
:
651 aResult
= WindowsUIUtils::ComputeTextScaleFactor();
655 res
= NS_ERROR_FAILURE
;
660 LookAndFeelFont
nsLookAndFeel::GetLookAndFeelFontInternal(
661 const LOGFONTW
& aLogFont
, bool aUseShellDlg
) {
662 LookAndFeelFont result
{};
664 result
.haveFont() = false;
666 // Get scaling factor from physical to logical pixels
668 1.0 / WinUtils::SystemScaleFactor() / LookAndFeel::GetTextScaleFactor();
670 // The lfHeight is in pixels, and it needs to be adjusted for the
671 // device it will be displayed on.
672 // Screens and Printers will differ in DPI
674 // So this accounts for the difference in the DeviceContexts
675 // The pixelScale will typically be 1.0 for the screen
676 // (though larger for hi-dpi screens where the Windows resolution
677 // scale factor is 125% or 150% or even more), and could be
678 // any value when going to a printer, for example pixelScale is
679 // 6.25 when going to a 600dpi printer.
680 float pixelHeight
= -aLogFont
.lfHeight
;
681 if (pixelHeight
< 0) {
682 nsAutoFont
hFont(::CreateFontIndirectW(&aLogFont
));
687 nsAutoHDC
dc(::GetDC(nullptr));
688 HGDIOBJ hObject
= ::SelectObject(dc
, hFont
);
690 ::GetTextMetrics(dc
, &tm
);
691 ::SelectObject(dc
, hObject
);
693 pixelHeight
= tm
.tmAscent
;
696 pixelHeight
*= pixelScale
;
698 // we have problem on Simplified Chinese system because the system
699 // report the default font size is 8 points. but if we use 8, the text
700 // display very ugly. force it to be at 9 points (12 pixels) on that
701 // system (cp936), but leave other sizes alone.
702 if (pixelHeight
< 12 && ::GetACP() == 936) {
706 result
.haveFont() = true;
709 result
.name() = u
"MS Shell Dlg 2"_ns
;
711 result
.name() = aLogFont
.lfFaceName
;
714 result
.size() = pixelHeight
;
715 result
.italic() = !!aLogFont
.lfItalic
;
716 // FIXME: Other weights?
718 ((aLogFont
.lfWeight
== FW_BOLD
) ? FontWeight::BOLD
: FontWeight::NORMAL
)
724 LookAndFeelFont
nsLookAndFeel::GetLookAndFeelFont(LookAndFeel::FontID anID
) {
725 LookAndFeelFont result
{};
727 result
.haveFont() = false;
729 // FontID::Icon is handled differently than the others
730 if (anID
== LookAndFeel::FontID::Icon
) {
732 if (::SystemParametersInfoW(SPI_GETICONTITLELOGFONT
, sizeof(logFont
),
733 (PVOID
)&logFont
, 0)) {
734 result
= GetLookAndFeelFontInternal(logFont
, false);
739 NONCLIENTMETRICSW ncm
;
740 ncm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
741 if (!::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
, sizeof(ncm
),
747 case LookAndFeel::FontID::Menu
:
748 case LookAndFeel::FontID::MozPullDownMenu
:
749 result
= GetLookAndFeelFontInternal(ncm
.lfMenuFont
, false);
751 case LookAndFeel::FontID::Caption
:
752 result
= GetLookAndFeelFontInternal(ncm
.lfCaptionFont
, false);
754 case LookAndFeel::FontID::SmallCaption
:
755 result
= GetLookAndFeelFontInternal(ncm
.lfSmCaptionFont
, false);
757 case LookAndFeel::FontID::StatusBar
:
758 result
= GetLookAndFeelFontInternal(ncm
.lfStatusFont
, false);
760 case LookAndFeel::FontID::MozButton
:
761 case LookAndFeel::FontID::MozField
:
762 case LookAndFeel::FontID::MozList
:
763 // XXX It's not clear to me whether this is exactly the right
764 // set of LookAndFeel values to map to the dialog font; we may
765 // want to add or remove cases here after reviewing the visual
766 // results under various Windows versions.
767 result
= GetLookAndFeelFontInternal(ncm
.lfMessageFont
, true);
770 result
= GetLookAndFeelFontInternal(ncm
.lfMessageFont
, false);
777 bool nsLookAndFeel::NativeGetFont(LookAndFeel::FontID anID
, nsString
& aFontName
,
778 gfxFontStyle
& aFontStyle
) {
779 LookAndFeelFont font
= GetLookAndFeelFont(anID
);
780 return LookAndFeelFontToStyle(font
, aFontName
, aFontStyle
);
784 char16_t
nsLookAndFeel::GetPasswordCharacterImpl() {
785 #define UNICODE_BLACK_CIRCLE_CHAR 0x25cf
786 return UNICODE_BLACK_CIRCLE_CHAR
;
789 static Maybe
<nscolor
> GetAccentColorText(const Maybe
<nscolor
>& aAccentColor
) {
793 // We want the color that we return for text that will be drawn over
794 // a background that has the accent color to have good contrast with
795 // the accent color. Windows itself uses either white or black text
796 // depending on how light or dark the accent color is. We do the same
797 // here based on the luminance of the accent color with a threshhold
798 // value. This algorithm should match what Windows does. It comes from:
800 // https://docs.microsoft.com/en-us/windows/uwp/style/color
801 float luminance
= (NS_GET_R(*aAccentColor
) * 2 + NS_GET_G(*aAccentColor
) * 5 +
802 NS_GET_B(*aAccentColor
)) /
805 return Some(luminance
<= 128 ? NS_RGB(255, 255, 255) : NS_RGB(0, 0, 0));
808 nscolor
nsLookAndFeel::GetColorForSysColorIndex(int index
) {
809 MOZ_ASSERT(index
>= SYS_COLOR_MIN
&& index
<= SYS_COLOR_MAX
);
810 return mSysColorTable
[index
- SYS_COLOR_MIN
];
813 void nsLookAndFeel::EnsureInit() {
819 mColorAccent
= WindowsUIUtils::GetAccentColor();
820 mColorAccentText
= GetAccentColorText(mColorAccent
);
822 if (nsUXThemeData::IsAppThemed()) {
823 mColorMenuHoverText
=
824 ::GetColorFromTheme(eUXMenu
, MENU_POPUPITEM
, MPI_HOT
, TMT_TEXTCOLOR
);
825 mColorMediaText
= ::GetColorFromTheme(eUXMediaToolbar
, TP_BUTTON
, TS_NORMAL
,
827 mColorCommunicationsText
= ::GetColorFromTheme(
828 eUXCommunicationsToolbar
, TP_BUTTON
, TS_NORMAL
, TMT_TEXTCOLOR
);
831 // Fill out the sys color table.
832 for (int i
= SYS_COLOR_MIN
; i
<= SYS_COLOR_MAX
; ++i
) {
833 mSysColorTable
[i
- SYS_COLOR_MIN
] = [&] {
834 if (auto c
= WindowsUIUtils::GetSystemColor(ColorScheme::Light
, i
)) {
837 DWORD color
= ::GetSysColor(i
);
838 return COLOREF_2_NSRGB(color
);
843 WindowsUIUtils::GetSystemColor(ColorScheme::Dark
, COLOR_HIGHLIGHT
);
845 WindowsUIUtils::GetSystemColor(ColorScheme::Dark
, COLOR_HIGHLIGHTTEXT
);