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 nsresult
nsLookAndFeel::NativeGetColor(ColorID aID
, ColorScheme aScheme
,
92 auto IsHighlightColor
= [&] {
94 case ColorID::MozMenuhover
:
95 return !LookAndFeel::WindowsNonNativeMenusEnabled();
96 case ColorID::Highlight
:
97 case ColorID::Selecteditem
:
98 // We prefer the generic dark selection color if we don't have an
100 return aScheme
!= ColorScheme::Dark
|| mDarkHighlight
;
101 case ColorID::IMESelectedRawTextBackground
:
102 case ColorID::IMESelectedConvertedTextBackground
:
109 auto IsHighlightTextColor
= [&] {
111 case ColorID::MozMenubarhovertext
:
112 if (LookAndFeel::WindowsNonNativeMenusEnabled()) {
115 if (!nsUXThemeData::IsAppThemed()) {
116 return nsUXThemeData::AreFlatMenusEnabled();
119 case ColorID::MozMenuhovertext
:
120 if (LookAndFeel::WindowsNonNativeMenusEnabled()) {
123 return !mColorMenuHoverText
;
124 case ColorID::Highlighttext
:
125 case ColorID::Selecteditemtext
:
126 // We prefer the generic dark selection color if we don't have an
128 return aScheme
!= ColorScheme::Dark
|| mDarkHighlightText
;
129 case ColorID::IMESelectedRawTextForeground
:
130 case ColorID::IMESelectedConvertedTextForeground
:
131 case ColorID::MozDragtargetzone
:
138 if (IsHighlightColor()) {
139 if (aScheme
== ColorScheme::Dark
&& mDarkHighlight
) {
140 aColor
= *mDarkHighlight
;
142 aColor
= GetColorForSysColorIndex(COLOR_HIGHLIGHT
);
147 if (IsHighlightTextColor()) {
148 if (aScheme
== ColorScheme::Dark
&& mDarkHighlightText
) {
149 aColor
= *mDarkHighlightText
;
151 aColor
= GetColorForSysColorIndex(COLOR_HIGHLIGHTTEXT
);
156 if (aScheme
== ColorScheme::Dark
) {
157 if (auto color
= GenericDarkColor(aID
)) {
163 static constexpr auto kNonNativeMenuText
= NS_RGB(0x15, 0x14, 0x1a);
164 nsresult res
= NS_OK
;
167 case ColorID::IMERawInputBackground
:
168 case ColorID::IMEConvertedTextBackground
:
169 aColor
= NS_TRANSPARENT
;
171 case ColorID::IMERawInputForeground
:
172 case ColorID::IMEConvertedTextForeground
:
173 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
175 case ColorID::IMERawInputUnderline
:
176 case ColorID::IMEConvertedTextUnderline
:
177 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
179 case ColorID::IMESelectedRawTextUnderline
:
180 case ColorID::IMESelectedConvertedTextUnderline
:
181 aColor
= NS_TRANSPARENT
;
183 case ColorID::SpellCheckerUnderline
:
184 aColor
= NS_RGB(0xff, 0, 0);
187 // New CSS 2 Color definitions
188 case ColorID::Activeborder
:
189 idx
= COLOR_ACTIVEBORDER
;
191 case ColorID::Activecaption
:
192 idx
= COLOR_ACTIVECAPTION
;
194 case ColorID::Appworkspace
:
195 idx
= COLOR_APPWORKSPACE
;
197 case ColorID::Background
:
198 idx
= COLOR_BACKGROUND
;
200 case ColorID::Buttonface
:
201 case ColorID::MozButtonhoverface
:
202 case ColorID::MozButtonactiveface
:
203 case ColorID::MozButtondisabledface
:
206 case ColorID::Buttonhighlight
:
207 idx
= COLOR_BTNHIGHLIGHT
;
209 case ColorID::Buttonshadow
:
210 idx
= COLOR_BTNSHADOW
;
212 case ColorID::Buttontext
:
213 case ColorID::MozButtonhovertext
:
214 case ColorID::MozButtonactivetext
:
217 case ColorID::Captiontext
:
218 idx
= COLOR_CAPTIONTEXT
;
220 case ColorID::MozCellhighlighttext
:
221 aColor
= NS_RGB(0, 0, 0);
223 case ColorID::MozCellhighlight
:
224 aColor
= NS_RGB(206, 206, 206);
226 case ColorID::Graytext
:
227 idx
= COLOR_GRAYTEXT
;
229 case ColorID::MozMenubarhovertext
:
230 if (LookAndFeel::WindowsNonNativeMenusEnabled()) {
231 aColor
= kNonNativeMenuText
;
234 if (!nsUXThemeData::IsAppThemed()) {
235 idx
= COLOR_MENUTEXT
;
239 case ColorID::MozMenuhovertext
:
240 if (LookAndFeel::WindowsNonNativeMenusEnabled()) {
241 aColor
= kNonNativeMenuText
;
244 if (mColorMenuHoverText
) {
245 aColor
= *mColorMenuHoverText
;
248 idx
= COLOR_HIGHLIGHTTEXT
;
250 case ColorID::MozMenuhover
:
251 MOZ_ASSERT(LookAndFeel::WindowsNonNativeMenusEnabled());
252 aColor
= NS_RGB(0xe0, 0xe0, 0xe6);
254 case ColorID::MozMenuhoverdisabled
:
255 if (LookAndFeel::WindowsNonNativeMenusEnabled()) {
256 aColor
= NS_RGB(0xf0, 0xf0, 0xf3);
259 aColor
= NS_TRANSPARENT
;
261 case ColorID::Inactiveborder
:
262 idx
= COLOR_INACTIVEBORDER
;
264 case ColorID::Inactivecaption
:
265 idx
= COLOR_INACTIVECAPTION
;
267 case ColorID::Inactivecaptiontext
:
268 idx
= COLOR_INACTIVECAPTIONTEXT
;
270 case ColorID::Infobackground
:
273 case ColorID::Infotext
:
274 idx
= COLOR_INFOTEXT
;
277 if (LookAndFeel::WindowsNonNativeMenusEnabled()) {
278 aColor
= NS_RGB(0xf9, 0xf9, 0xfb);
283 case ColorID::Menutext
:
284 case ColorID::MozMenubartext
:
285 if (LookAndFeel::WindowsNonNativeMenusEnabled()) {
286 aColor
= kNonNativeMenuText
;
289 idx
= COLOR_MENUTEXT
;
291 case ColorID::Scrollbar
:
292 idx
= COLOR_SCROLLBAR
;
294 case ColorID::Threeddarkshadow
:
295 idx
= COLOR_3DDKSHADOW
;
297 case ColorID::Threedface
:
300 case ColorID::Threedhighlight
:
301 idx
= COLOR_3DHIGHLIGHT
;
303 case ColorID::Threedlightshadow
:
304 case ColorID::MozDisabledfield
:
307 case ColorID::Threedshadow
:
308 idx
= COLOR_3DSHADOW
;
310 case ColorID::Window
:
313 case ColorID::Windowframe
:
314 idx
= COLOR_WINDOWFRAME
;
316 case ColorID::Windowtext
:
317 idx
= COLOR_WINDOWTEXT
;
319 case ColorID::MozEventreerow
:
320 case ColorID::MozOddtreerow
:
322 case ColorID::MozCombobox
:
325 case ColorID::Fieldtext
:
326 case ColorID::MozComboboxtext
:
327 idx
= COLOR_WINDOWTEXT
;
329 case ColorID::MozDialog
:
332 case ColorID::Accentcolor
:
334 aColor
= *mColorAccent
;
336 // Seems to be the default color (hardcoded because of bug 1065998)
337 aColor
= NS_RGB(0, 120, 215);
340 case ColorID::Accentcolortext
:
341 if (mColorAccentText
) {
342 aColor
= *mColorAccentText
;
344 aColor
= NS_RGB(255, 255, 255);
347 case ColorID::MozWinMediatext
:
348 if (mColorMediaText
) {
349 aColor
= *mColorMediaText
;
352 // if we've gotten here just return -moz-dialogtext instead
353 idx
= COLOR_WINDOWTEXT
;
355 case ColorID::MozWinCommunicationstext
:
356 if (mColorCommunicationsText
) {
357 aColor
= *mColorCommunicationsText
;
360 // if we've gotten here just return -moz-dialogtext instead
361 idx
= COLOR_WINDOWTEXT
;
363 case ColorID::MozDialogtext
:
364 case ColorID::MozColheadertext
:
365 case ColorID::MozColheaderhovertext
:
366 idx
= COLOR_WINDOWTEXT
;
368 case ColorID::MozButtondefault
:
369 idx
= COLOR_3DDKSHADOW
;
371 case ColorID::MozNativehyperlinktext
:
372 idx
= COLOR_HOTLIGHT
;
376 res
= NS_ERROR_FAILURE
;
380 aColor
= GetColorForSysColorIndex(idx
);
385 nsresult
nsLookAndFeel::NativeGetInt(IntID aID
, int32_t& aResult
) {
387 nsresult res
= NS_OK
;
390 case IntID::ScrollButtonLeftMouseButtonAction
:
393 case IntID::ScrollButtonMiddleMouseButtonAction
:
394 case IntID::ScrollButtonRightMouseButtonAction
:
397 case IntID::CaretBlinkTime
:
398 aResult
= static_cast<int32_t>(::GetCaretBlinkTime());
400 case IntID::CaretBlinkCount
: {
401 int32_t timeout
= GetSystemParam(SPI_GETCARETTIMEOUT
, 5000);
402 auto blinkTime
= ::GetCaretBlinkTime();
403 if (timeout
<= 0 || blinkTime
<= 0) {
407 // 2 * blinkTime because this integer is a full blink cycle.
408 aResult
= std::ceil(float(timeout
) / (2.0f
* float(blinkTime
)));
412 case IntID::CaretWidth
:
415 case IntID::ShowCaretDuringSelection
:
418 case IntID::SelectTextfieldsOnKeyFocus
:
419 // Select textfield content when focused by kbd
420 // used by EventStateManager::sTextfieldSelectModel
423 case IntID::SubmenuDelay
:
424 // This will default to the Windows' default
426 aResult
= GetSystemParam(SPI_GETMENUSHOWDELAY
, 400);
428 case IntID::TooltipDelay
:
431 case IntID::MenusCanOverlapOSBar
:
432 // we want XUL popups to be able to overlap the task bar.
435 case IntID::DragThresholdX
:
436 // The system metric is the number of pixels at which a drag should
437 // start. Our look and feel metric is the number of pixels you can
438 // move before starting a drag, so subtract 1.
440 aResult
= ::GetSystemMetrics(SM_CXDRAG
) - 1;
442 case IntID::DragThresholdY
:
443 aResult
= ::GetSystemMetrics(SM_CYDRAG
) - 1;
445 case IntID::UseAccessibilityTheme
:
446 // High contrast is a misnomer under Win32 -- any theme can be used with
447 // it, e.g. normal contrast with large fonts, low contrast, etc. The high
448 // contrast flag really means -- use this theme and don't override it.
449 aResult
= nsUXThemeData::IsHighContrastOn();
451 case IntID::ScrollArrowStyle
:
452 aResult
= eScrollArrowStyle_Single
;
454 case IntID::TreeOpenDelay
:
457 case IntID::TreeCloseDelay
:
460 case IntID::TreeLazyScrollDelay
:
463 case IntID::TreeScrollDelay
:
466 case IntID::TreeScrollLinesMax
:
469 case IntID::WindowsClassic
:
470 aResult
= !nsUXThemeData::IsAppThemed();
472 case IntID::WindowsDefaultTheme
:
473 aResult
= nsUXThemeData::IsDefaultWindowTheme();
475 case IntID::DWMCompositor
:
476 aResult
= gfxWindowsPlatform::GetPlatform()->DwmCompositionEnabled();
478 case IntID::WindowsAccentColorInTitlebar
: {
480 if (NS_WARN_IF(!mColorAccent
)) {
485 mDwmKey
= do_CreateInstance("@mozilla.org/windows-registry-key;1");
490 uint32_t colorPrevalence
;
491 nsresult rv
= mDwmKey
->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER
,
492 u
"SOFTWARE\\Microsoft\\Windows\\DWM"_ns
,
493 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
494 if (NS_WARN_IF(NS_FAILED(rv
))) {
498 // The ColorPrevalence value is set to 1 when the "Show color on title
499 // bar" setting in the Color section of Window's Personalization settings
501 aResult
= (NS_SUCCEEDED(mDwmKey
->ReadIntValue(u
"ColorPrevalence"_ns
,
502 &colorPrevalence
)) &&
503 colorPrevalence
== 1)
509 case IntID::WindowsGlass
:
510 // Aero Glass is only available prior to Windows 8 when DWM is used.
511 aResult
= (gfxWindowsPlatform::GetPlatform()->DwmCompositionEnabled() &&
514 case IntID::AlertNotificationOrigin
:
517 // Get task bar window handle
518 HWND shellWindow
= FindWindowW(L
"Shell_TrayWnd", nullptr);
520 if (shellWindow
!= nullptr) {
521 // Determine position
522 APPBARDATA appBarData
;
523 appBarData
.hWnd
= shellWindow
;
524 appBarData
.cbSize
= sizeof(appBarData
);
525 if (SHAppBarMessage(ABM_GETTASKBARPOS
, &appBarData
)) {
526 // Set alert origin as a bit field - see LookAndFeel.h
527 // 0 represents bottom right, sliding vertically.
528 switch (appBarData
.uEdge
) {
530 aResult
= NS_ALERT_HORIZONTAL
| NS_ALERT_LEFT
;
533 aResult
= NS_ALERT_HORIZONTAL
;
536 aResult
= NS_ALERT_TOP
;
539 // If the task bar is right-to-left,
540 // move the origin to the left
541 if (::GetWindowLong(shellWindow
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
)
542 aResult
|= NS_ALERT_LEFT
;
549 case IntID::IMERawInputUnderlineStyle
:
550 case IntID::IMEConvertedTextUnderlineStyle
:
551 aResult
= NS_STYLE_TEXT_DECORATION_STYLE_DASHED
;
553 case IntID::IMESelectedRawTextUnderlineStyle
:
554 case IntID::IMESelectedConvertedTextUnderline
:
555 aResult
= NS_STYLE_TEXT_DECORATION_STYLE_NONE
;
557 case IntID::SpellCheckerUnderlineStyle
:
558 aResult
= NS_STYLE_TEXT_DECORATION_STYLE_WAVY
;
560 case IntID::ScrollbarButtonAutoRepeatBehavior
:
563 case IntID::SwipeAnimationEnabled
:
564 // Forcibly enable the swipe animation on Windows. It doesn't matter on
565 // platforms where "Drag two fingers to scroll" isn't supported since on
566 // the platforms we will never generate any swipe gesture events.
569 case IntID::UseOverlayScrollbars
:
570 aResult
= WindowsUIUtils::ComputeOverlayScrollbars();
572 case IntID::AllowOverlayScrollbarsOverlap
:
575 case IntID::ScrollbarDisplayOnMouseMove
:
578 case IntID::ScrollbarFadeBeginDelay
:
581 case IntID::ScrollbarFadeDuration
:
584 case IntID::ContextMenuOffsetVertical
:
585 case IntID::ContextMenuOffsetHorizontal
:
588 case IntID::SystemUsesDarkTheme
:
589 res
= SystemWantsDarkTheme(aResult
);
591 case IntID::SystemVerticalScrollbarWidth
:
592 aResult
= WinUtils::GetSystemMetricsForDpi(SM_CXVSCROLL
, 96);
594 case IntID::SystemHorizontalScrollbarHeight
:
595 aResult
= WinUtils::GetSystemMetricsForDpi(SM_CXHSCROLL
, 96);
597 case IntID::PrefersReducedMotion
: {
598 BOOL enableAnimation
= TRUE
;
599 ::SystemParametersInfoW(SPI_GETCLIENTAREAANIMATION
, 0, &enableAnimation
,
601 aResult
= enableAnimation
? 0 : 1;
604 case IntID::PrimaryPointerCapabilities
: {
605 aResult
= static_cast<int32_t>(
606 widget::WinUtils::GetPrimaryPointerCapabilities());
609 case IntID::AllPointerCapabilities
: {
611 static_cast<int32_t>(widget::WinUtils::GetAllPointerCapabilities());
614 case IntID::TouchDeviceSupportPresent
:
615 aResult
= WinUtils::IsTouchDeviceSupportPresent() ? 1 : 0;
619 res
= NS_ERROR_FAILURE
;
624 nsresult
nsLookAndFeel::NativeGetFloat(FloatID aID
, float& aResult
) {
625 nsresult res
= NS_OK
;
628 case FloatID::IMEUnderlineRelativeSize
:
631 case FloatID::SpellCheckerUnderlineRelativeSize
:
634 case FloatID::TextScaleFactor
:
635 aResult
= WindowsUIUtils::ComputeTextScaleFactor();
639 res
= NS_ERROR_FAILURE
;
644 LookAndFeelFont
nsLookAndFeel::GetLookAndFeelFontInternal(
645 const LOGFONTW
& aLogFont
, bool aUseShellDlg
) {
646 LookAndFeelFont result
{};
648 result
.haveFont() = false;
650 // Get scaling factor from physical to logical pixels
652 1.0 / WinUtils::SystemScaleFactor() / LookAndFeel::GetTextScaleFactor();
654 // The lfHeight is in pixels, and it needs to be adjusted for the
655 // device it will be displayed on.
656 // Screens and Printers will differ in DPI
658 // So this accounts for the difference in the DeviceContexts
659 // The pixelScale will typically be 1.0 for the screen
660 // (though larger for hi-dpi screens where the Windows resolution
661 // scale factor is 125% or 150% or even more), and could be
662 // any value when going to a printer, for example pixelScale is
663 // 6.25 when going to a 600dpi printer.
664 float pixelHeight
= -aLogFont
.lfHeight
;
665 if (pixelHeight
< 0) {
666 nsAutoFont
hFont(::CreateFontIndirectW(&aLogFont
));
671 nsAutoHDC
dc(::GetDC(nullptr));
672 HGDIOBJ hObject
= ::SelectObject(dc
, hFont
);
674 ::GetTextMetrics(dc
, &tm
);
675 ::SelectObject(dc
, hObject
);
677 pixelHeight
= tm
.tmAscent
;
680 pixelHeight
*= pixelScale
;
682 // we have problem on Simplified Chinese system because the system
683 // report the default font size is 8 points. but if we use 8, the text
684 // display very ugly. force it to be at 9 points (12 pixels) on that
685 // system (cp936), but leave other sizes alone.
686 if (pixelHeight
< 12 && ::GetACP() == 936) {
690 result
.haveFont() = true;
693 result
.name() = u
"MS Shell Dlg 2"_ns
;
695 result
.name() = aLogFont
.lfFaceName
;
698 result
.size() = pixelHeight
;
699 result
.italic() = !!aLogFont
.lfItalic
;
700 // FIXME: Other weights?
702 ((aLogFont
.lfWeight
== FW_BOLD
) ? FontWeight::BOLD
: FontWeight::NORMAL
)
708 LookAndFeelFont
nsLookAndFeel::GetLookAndFeelFont(LookAndFeel::FontID anID
) {
709 LookAndFeelFont result
{};
711 result
.haveFont() = false;
713 // FontID::Icon is handled differently than the others
714 if (anID
== LookAndFeel::FontID::Icon
) {
716 if (::SystemParametersInfoW(SPI_GETICONTITLELOGFONT
, sizeof(logFont
),
717 (PVOID
)&logFont
, 0)) {
718 result
= GetLookAndFeelFontInternal(logFont
, false);
723 NONCLIENTMETRICSW ncm
;
724 ncm
.cbSize
= sizeof(NONCLIENTMETRICSW
);
725 if (!::SystemParametersInfoW(SPI_GETNONCLIENTMETRICS
, sizeof(ncm
),
731 case LookAndFeel::FontID::Menu
:
732 case LookAndFeel::FontID::MozPullDownMenu
:
733 result
= GetLookAndFeelFontInternal(ncm
.lfMenuFont
, false);
735 case LookAndFeel::FontID::Caption
:
736 result
= GetLookAndFeelFontInternal(ncm
.lfCaptionFont
, false);
738 case LookAndFeel::FontID::SmallCaption
:
739 result
= GetLookAndFeelFontInternal(ncm
.lfSmCaptionFont
, false);
741 case LookAndFeel::FontID::StatusBar
:
742 result
= GetLookAndFeelFontInternal(ncm
.lfStatusFont
, false);
744 case LookAndFeel::FontID::MozDialog
:
745 case LookAndFeel::FontID::MozButton
:
746 case LookAndFeel::FontID::MozField
:
747 case LookAndFeel::FontID::MozList
:
748 // XXX It's not clear to me whether this is exactly the right
749 // set of LookAndFeel values to map to the dialog font; we may
750 // want to add or remove cases here after reviewing the visual
751 // results under various Windows versions.
752 result
= GetLookAndFeelFontInternal(ncm
.lfMessageFont
, true);
755 result
= GetLookAndFeelFontInternal(ncm
.lfMessageFont
, false);
762 bool nsLookAndFeel::NativeGetFont(LookAndFeel::FontID anID
, nsString
& aFontName
,
763 gfxFontStyle
& aFontStyle
) {
764 LookAndFeelFont font
= GetLookAndFeelFont(anID
);
765 return LookAndFeelFontToStyle(font
, aFontName
, aFontStyle
);
769 char16_t
nsLookAndFeel::GetPasswordCharacterImpl() {
770 #define UNICODE_BLACK_CIRCLE_CHAR 0x25cf
771 return UNICODE_BLACK_CIRCLE_CHAR
;
774 static Maybe
<nscolor
> GetAccentColorText(const Maybe
<nscolor
>& aAccentColor
) {
778 // We want the color that we return for text that will be drawn over
779 // a background that has the accent color to have good contrast with
780 // the accent color. Windows itself uses either white or black text
781 // depending on how light or dark the accent color is. We do the same
782 // here based on the luminance of the accent color with a threshhold
783 // value. This algorithm should match what Windows does. It comes from:
785 // https://docs.microsoft.com/en-us/windows/uwp/style/color
786 float luminance
= (NS_GET_R(*aAccentColor
) * 2 + NS_GET_G(*aAccentColor
) * 5 +
787 NS_GET_B(*aAccentColor
)) /
790 return Some(luminance
<= 128 ? NS_RGB(255, 255, 255) : NS_RGB(0, 0, 0));
793 nscolor
nsLookAndFeel::GetColorForSysColorIndex(int index
) {
794 MOZ_ASSERT(index
>= SYS_COLOR_MIN
&& index
<= SYS_COLOR_MAX
);
795 return mSysColorTable
[index
- SYS_COLOR_MIN
];
798 void nsLookAndFeel::EnsureInit() {
804 mColorAccent
= WindowsUIUtils::GetAccentColor();
805 mColorAccentText
= GetAccentColorText(mColorAccent
);
807 if (nsUXThemeData::IsAppThemed()) {
808 mColorMenuHoverText
=
809 ::GetColorFromTheme(eUXMenu
, MENU_POPUPITEM
, MPI_HOT
, TMT_TEXTCOLOR
);
810 mColorMediaText
= ::GetColorFromTheme(eUXMediaToolbar
, TP_BUTTON
, TS_NORMAL
,
812 mColorCommunicationsText
= ::GetColorFromTheme(
813 eUXCommunicationsToolbar
, TP_BUTTON
, TS_NORMAL
, TMT_TEXTCOLOR
);
816 // Fill out the sys color table.
817 for (int i
= SYS_COLOR_MIN
; i
<= SYS_COLOR_MAX
; ++i
) {
818 mSysColorTable
[i
- SYS_COLOR_MIN
] = [&] {
819 if (auto c
= WindowsUIUtils::GetSystemColor(ColorScheme::Light
, i
)) {
822 DWORD color
= ::GetSysColor(i
);
823 return COLOREF_2_NSRGB(color
);
828 WindowsUIUtils::GetSystemColor(ColorScheme::Dark
, COLOR_HIGHLIGHT
);
830 WindowsUIUtils::GetSystemColor(ColorScheme::Dark
, COLOR_HIGHLIGHTTEXT
);