1 /* -*- Mode: C++; tab-width: 20; 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 "nsStyleConsts.h"
7 #include "nsXULAppAPI.h"
8 #include "nsLookAndFeel.h"
11 #include "gfxFontConstants.h"
12 #include "mozilla/FontPropertyTypes.h"
13 #include "mozilla/gfx/2D.h"
14 #include "mozilla/Preferences.h"
15 #include "mozilla/StaticPrefs_widget.h"
16 #include "mozilla/java/GeckoAppShellWrappers.h"
17 #include "mozilla/java/GeckoRuntimeWrappers.h"
18 #include "mozilla/java/GeckoSystemStateListenerWrappers.h"
19 #include "ThemeColors.h"
21 using namespace mozilla
;
22 using namespace mozilla::widget
;
24 static const char16_t UNICODE_BULLET
= 0x2022;
26 static void AccentColorPrefChanged(const char*, void*) {
27 LookAndFeel::NotifyChangedAllWindows(widget::ThemeChangeKind::Style
);
30 nsLookAndFeel::nsLookAndFeel() {
31 Preferences::RegisterCallback(
32 AccentColorPrefChanged
,
34 StaticPrefs::GetPrefName_widget_non_native_theme_use_theme_accent()));
37 nsLookAndFeel::~nsLookAndFeel() {
38 Preferences::UnregisterCallback(
39 AccentColorPrefChanged
,
41 StaticPrefs::GetPrefName_widget_non_native_theme_use_theme_accent()));
44 nsresult
nsLookAndFeel::GetSystemColors() {
45 if (!jni::IsAvailable()) {
46 return NS_ERROR_FAILURE
;
49 auto arr
= java::GeckoAppShell::GetSystemColors();
51 return NS_ERROR_FAILURE
;
54 JNIEnv
* const env
= arr
.Env();
55 uint32_t len
= static_cast<uint32_t>(env
->GetArrayLength(arr
.Get()));
56 jint
* elements
= env
->GetIntArrayElements(arr
.Get(), 0);
58 uint32_t colorsCount
= sizeof(AndroidSystemColors
) / sizeof(nscolor
);
59 if (len
< colorsCount
) colorsCount
= len
;
61 // Convert Android colors to nscolor by switching R and B in the ARGB 32 bit
63 nscolor
* colors
= (nscolor
*)&mSystemColors
;
65 for (uint32_t i
= 0; i
< colorsCount
; i
++) {
66 uint32_t androidColor
= static_cast<uint32_t>(elements
[i
]);
67 uint8_t r
= (androidColor
& 0x00ff0000) >> 16;
68 uint8_t b
= (androidColor
& 0x000000ff);
69 colors
[i
] = (androidColor
& 0xff00ff00) | (b
<< 16) | r
;
72 env
->ReleaseIntArrayElements(arr
.Get(), elements
, 0);
77 void nsLookAndFeel::NativeInit() {
78 EnsureInitSystemColors();
79 EnsureInitShowPassword();
83 void nsLookAndFeel::RefreshImpl() {
84 mInitializedSystemColors
= false;
85 mInitializedShowPassword
= false;
86 nsXPLookAndFeel::RefreshImpl();
89 nsresult
nsLookAndFeel::NativeGetColor(ColorID aID
, ColorScheme aColorScheme
,
91 EnsureInitSystemColors();
92 if (!mInitializedSystemColors
) {
93 // Failure to initialize colors is an error condition. Return black.
95 return NS_ERROR_FAILURE
;
98 // Highlight/Highlighttext have native equivalents that we can map to (on
99 // Android) which should work fine, regardless of the color-scheme.
101 case ColorID::Highlight
: {
102 // Matched to action_accent in java codebase. This works fine with both
103 // light and dark color scheme.
105 Color(ColorID::MozAccentColor
, aColorScheme
, UseStandins::No
);
107 NS_RGBA(NS_GET_R(accent
), NS_GET_G(accent
), NS_GET_B(accent
), 78);
110 case ColorID::Highlighttext
:
111 // Selection background is transparent enough that any foreground color
113 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
119 if (aColorScheme
== ColorScheme::Dark
) {
120 if (auto darkColor
= GenericDarkColor(aID
)) {
126 // XXX we'll want to use context.obtainStyledAttributes on the java side to
127 // get all of these; see TextView.java for a good example.
128 auto UseNativeAccent
= [this] {
129 return mSystemColors
.colorAccent
&&
130 StaticPrefs::widget_non_native_theme_use_theme_accent();
134 // These colors don't seem to be used for anything anymore in Mozilla
135 // The CSS2 colors below are used.
136 case ColorID::MozMenubartext
:
137 aColor
= mSystemColors
.colorForeground
;
140 case ColorID::ThemedScrollbarThumbInactive
:
141 case ColorID::ThemedScrollbarThumb
:
142 // We don't need to care about the Active and Hover colors because Android
143 // scrollbars can't be hovered (they always have pointer-events: none).
144 aColor
= NS_RGBA(119, 119, 119, 102);
147 case ColorID::IMESelectedRawTextBackground
:
148 case ColorID::IMESelectedConvertedTextBackground
:
149 aColor
= mSystemColors
.textColorHighlight
;
151 case ColorID::IMESelectedRawTextForeground
:
152 case ColorID::IMESelectedConvertedTextForeground
:
153 aColor
= mSystemColors
.textColorPrimaryInverse
;
155 case ColorID::IMERawInputBackground
:
156 case ColorID::IMEConvertedTextBackground
:
157 aColor
= NS_TRANSPARENT
;
159 case ColorID::IMERawInputForeground
:
160 case ColorID::IMEConvertedTextForeground
:
161 case ColorID::IMERawInputUnderline
:
162 case ColorID::IMEConvertedTextUnderline
:
163 aColor
= NS_SAME_AS_FOREGROUND_COLOR
;
165 case ColorID::IMESelectedRawTextUnderline
:
166 case ColorID::IMESelectedConvertedTextUnderline
:
167 aColor
= NS_TRANSPARENT
;
169 case ColorID::SpellCheckerUnderline
:
170 aColor
= NS_RGB(0xff, 0x00, 0x00);
173 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
174 case ColorID::Activeborder
: // active window border
175 case ColorID::Appworkspace
: // MDI background color
176 case ColorID::Activecaption
: // active window caption background
177 case ColorID::Background
: // desktop background
178 case ColorID::Inactiveborder
: // inactive window border
179 case ColorID::Inactivecaption
: // inactive window caption
180 case ColorID::Scrollbar
: // scrollbar gray area
181 aColor
= mSystemColors
.colorBackground
;
183 case ColorID::Graytext
: // disabled text in windows, menus, etc.
184 aColor
= NS_RGB(0xb1, 0xa5, 0x98);
186 // FIXME: -moz-cellhighlight should show some kind of unfocused state.
187 case ColorID::MozCellhighlight
:
188 case ColorID::Selecteditem
:
189 case ColorID::MozAccentColor
:
190 aColor
= UseNativeAccent() ? mSystemColors
.colorAccent
191 : widget::sDefaultAccent
.ToABGR();
193 case ColorID::MozCellhighlighttext
:
194 case ColorID::Selecteditemtext
:
195 case ColorID::MozAccentColorForeground
:
196 aColor
= UseNativeAccent() ? ThemeColors::ComputeCustomAccentForeground(
197 mSystemColors
.colorAccent
)
198 : widget::sDefaultAccentForeground
.ToABGR();
200 case ColorID::Fieldtext
:
201 aColor
= NS_RGB(0x1a, 0x1a, 0x1a);
203 case ColorID::Inactivecaptiontext
:
204 // text in inactive window caption
205 aColor
= mSystemColors
.textColorTertiary
;
207 case ColorID::Infobackground
:
208 aColor
= NS_RGB(0xf5, 0xf5, 0xb5);
210 case ColorID::Infotext
:
211 case ColorID::Threeddarkshadow
: // 3-D shadow outer edge color
212 case ColorID::MozButtondefault
: // default button border color
213 aColor
= NS_RGB(0x00, 0x00, 0x00);
216 aColor
= NS_RGB(0xf7, 0xf5, 0xf3);
219 case ColorID::Buttonface
:
220 case ColorID::MozButtondisabledface
:
221 case ColorID::Threedface
:
222 case ColorID::Threedlightshadow
:
223 case ColorID::MozDisabledfield
:
224 aColor
= NS_RGB(0xec, 0xe7, 0xe2);
227 case ColorID::Buttonhighlight
:
229 case ColorID::Threedhighlight
:
230 case ColorID::MozCombobox
:
231 case ColorID::MozEventreerow
:
232 aColor
= NS_RGB(0xff, 0xff, 0xff);
235 case ColorID::Buttonshadow
:
236 case ColorID::Threedshadow
:
237 aColor
= NS_RGB(0xae, 0xa1, 0x94);
240 case ColorID::MozDialog
:
241 case ColorID::Window
:
242 case ColorID::Windowframe
:
243 aColor
= NS_RGB(0xef, 0xeb, 0xe7);
245 case ColorID::Buttontext
:
246 case ColorID::Captiontext
:
247 case ColorID::Menutext
:
248 case ColorID::MozButtonhovertext
:
249 case ColorID::MozDialogtext
:
250 case ColorID::MozComboboxtext
:
251 case ColorID::Windowtext
:
252 case ColorID::MozColheadertext
:
253 case ColorID::MozColheaderhovertext
:
254 aColor
= NS_RGB(0x10, 0x10, 0x10);
256 case ColorID::MozDragtargetzone
:
257 aColor
= mSystemColors
.textColorHighlight
;
259 case ColorID::MozButtonhoverface
:
260 case ColorID::MozButtonactiveface
:
261 aColor
= NS_RGB(0xf3, 0xf0, 0xed);
263 case ColorID::MozMenuhover
:
264 aColor
= NS_RGB(0xee, 0xee, 0xee);
266 case ColorID::MozMenubarhovertext
:
267 case ColorID::MozMenuhovertext
:
268 aColor
= NS_RGB(0x77, 0x77, 0x77);
270 case ColorID::MozOddtreerow
:
271 aColor
= NS_TRANSPARENT
;
273 case ColorID::MozNativehyperlinktext
:
274 aColor
= NS_RGB(0, 0, 0xee);
277 /* default color is BLACK */
279 return NS_ERROR_FAILURE
;
285 nsresult
nsLookAndFeel::NativeGetInt(IntID aID
, int32_t& aResult
) {
289 case IntID::ScrollButtonLeftMouseButtonAction
:
293 case IntID::ScrollButtonMiddleMouseButtonAction
:
294 case IntID::ScrollButtonRightMouseButtonAction
:
298 case IntID::CaretBlinkTime
:
302 case IntID::CaretBlinkCount
:
306 case IntID::CaretWidth
:
310 case IntID::ShowCaretDuringSelection
:
314 case IntID::SelectTextfieldsOnKeyFocus
:
315 // Select textfield content when focused by kbd
316 // used by EventStateManager::sTextfieldSelectModel
320 case IntID::SubmenuDelay
:
324 case IntID::TooltipDelay
:
328 case IntID::MenusCanOverlapOSBar
:
329 // we want XUL popups to be able to overlap the task bar.
333 case IntID::ScrollArrowStyle
:
334 aResult
= eScrollArrowStyle_Single
;
337 case IntID::ScrollSliderStyle
:
338 aResult
= eScrollThumbStyle_Proportional
;
341 case IntID::UseOverlayScrollbars
:
345 case IntID::SpellCheckerUnderlineStyle
:
346 aResult
= NS_STYLE_TEXT_DECORATION_STYLE_WAVY
;
349 case IntID::ScrollbarButtonAutoRepeatBehavior
:
353 case IntID::ContextMenuOffsetVertical
:
354 case IntID::ContextMenuOffsetHorizontal
:
358 case IntID::PrefersReducedMotion
:
359 aResult
= java::GeckoSystemStateListener::PrefersReducedMotion();
362 case IntID::PrimaryPointerCapabilities
:
363 aResult
= java::GeckoAppShell::GetAllPointerCapabilities();
365 // We cannot assume what is primary device, so we use Blink's way for web
366 // compatibility (https://crbug.com/136119#c6). If having coarse
367 // capability in any devices, return it.
368 if (aResult
& static_cast<int32_t>(PointerCapabilities::Coarse
)) {
369 aResult
= static_cast<int32_t>(PointerCapabilities::Coarse
);
373 case IntID::AllPointerCapabilities
:
374 aResult
= java::GeckoAppShell::GetAllPointerCapabilities();
377 case IntID::SystemUsesDarkTheme
: {
378 java::GeckoRuntime::LocalRef runtime
= java::GeckoRuntime::GetInstance();
379 aResult
= runtime
&& runtime
->UsesDarkTheme();
383 case IntID::DragThresholdX
:
384 case IntID::DragThresholdY
:
385 // Threshold where a tap becomes a drag, in 1/240" reference pixels.
389 case IntID::TouchDeviceSupportPresent
:
390 // Touch support is always enabled on android.
396 rv
= NS_ERROR_FAILURE
;
402 nsresult
nsLookAndFeel::NativeGetFloat(FloatID aID
, float& aResult
) {
406 case FloatID::IMEUnderlineRelativeSize
:
410 case FloatID::SpellCheckerUnderlineRelativeSize
:
416 rv
= NS_ERROR_FAILURE
;
422 bool nsLookAndFeel::NativeGetFont(FontID aID
, nsString
& aFontName
,
423 gfxFontStyle
& aFontStyle
) {
424 aFontName
.AssignLiteral("Roboto");
425 aFontStyle
.style
= FontSlantStyle::Normal();
426 aFontStyle
.weight
= FontWeight::Normal();
427 aFontStyle
.stretch
= FontStretch::Normal();
428 aFontStyle
.size
= 9.0 * 96.0f
/ 72.0f
;
429 aFontStyle
.systemFont
= true;
433 bool nsLookAndFeel::GetEchoPasswordImpl() {
434 EnsureInitShowPassword();
435 return mShowPassword
;
438 uint32_t nsLookAndFeel::GetPasswordMaskDelayImpl() {
439 // This value is hard-coded in Android OS's PasswordTransformationMethod.java
443 char16_t
nsLookAndFeel::GetPasswordCharacterImpl() {
444 // This value is hard-coded in Android OS's PasswordTransformationMethod.java
445 return UNICODE_BULLET
;
448 void nsLookAndFeel::EnsureInitSystemColors() {
449 if (!mInitializedSystemColors
) {
450 mInitializedSystemColors
= NS_SUCCEEDED(GetSystemColors());
454 void nsLookAndFeel::EnsureInitShowPassword() {
455 if (!mInitializedShowPassword
&& jni::IsAvailable()) {
456 mShowPassword
= java::GeckoAppShell::GetShowPasswordSetting();
457 mInitializedShowPassword
= true;