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/. */
5
6 #include "mozilla/dom/ContentChild.h"
7 #include "nsStyleConsts.h"
8 #include "nsXULAppAPI.h"
9 #include "nsLookAndFeel.h"
10 #include "gfxFont.h"
11 #include "gfxFontConstants.h"
12 #include "mozilla/FontPropertyTypes.h"
13 #include "mozilla/gfx/2D.h"
14 #include "mozilla/java/GeckoAppShellWrappers.h"
15 #include "mozilla/java/GeckoRuntimeWrappers.h"
16 #include "mozilla/java/GeckoSystemStateListenerWrappers.h"
17
18 using namespace mozilla;
19 using mozilla::dom::ContentChild;
20
21 static const char16_t UNICODE_BULLET = 0x2022;
22
23 nsLookAndFeel::nsLookAndFeel() = default;
24
~nsLookAndFeel()25 nsLookAndFeel::~nsLookAndFeel() {}
26
27 #define BG_PRELIGHT_COLOR NS_RGB(0xee, 0xee, 0xee)
28 #define FG_PRELIGHT_COLOR NS_RGB(0x77, 0x77, 0x77)
29 #define BLACK_COLOR NS_RGB(0x00, 0x00, 0x00)
30 #define DARK_GRAY_COLOR NS_RGB(0x40, 0x40, 0x40)
31 #define GRAY_COLOR NS_RGB(0x80, 0x80, 0x80)
32 #define LIGHT_GRAY_COLOR NS_RGB(0xa0, 0xa0, 0xa0)
33 #define RED_COLOR NS_RGB(0xff, 0x00, 0x00)
34
GetSystemColors()35 nsresult nsLookAndFeel::GetSystemColors() {
36 if (!jni::IsAvailable()) {
37 return NS_ERROR_FAILURE;
38 }
39
40 auto arr = java::GeckoAppShell::GetSystemColors();
41 if (!arr) {
42 return NS_ERROR_FAILURE;
43 }
44
45 JNIEnv* const env = arr.Env();
46 uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr.Get()));
47 jint* elements = env->GetIntArrayElements(arr.Get(), 0);
48
49 uint32_t colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor);
50 if (len < colorsCount) colorsCount = len;
51
52 // Convert Android colors to nscolor by switching R and B in the ARGB 32 bit
53 // value
54 nscolor* colors = (nscolor*)&mSystemColors;
55
56 for (uint32_t i = 0; i < colorsCount; i++) {
57 uint32_t androidColor = static_cast<uint32_t>(elements[i]);
58 uint8_t r = (androidColor & 0x00ff0000) >> 16;
59 uint8_t b = (androidColor & 0x000000ff);
60 colors[i] = (androidColor & 0xff00ff00) | (b << 16) | r;
61 }
62
63 env->ReleaseIntArrayElements(arr.Get(), elements, 0);
64
65 return NS_OK;
66 }
67
NativeInit()68 void nsLookAndFeel::NativeInit() {
69 EnsureInitSystemColors();
70 EnsureInitShowPassword();
71 RecordTelemetry();
72 }
73
74 /* virtual */
RefreshImpl()75 void nsLookAndFeel::RefreshImpl() {
76 nsXPLookAndFeel::RefreshImpl();
77
78 mInitializedSystemColors = false;
79 mInitializedShowPassword = false;
80 }
81
NativeGetColor(ColorID aID,ColorScheme,nscolor & aColor)82 nsresult nsLookAndFeel::NativeGetColor(ColorID aID, ColorScheme,
83 nscolor& aColor) {
84 nsresult rv = NS_OK;
85
86 EnsureInitSystemColors();
87 if (!mInitializedSystemColors) {
88 // Failure to initialize colors is an error condition. Return black.
89 aColor = 0;
90 return NS_ERROR_FAILURE;
91 }
92
93 // XXX we'll want to use context.obtainStyledAttributes on the java side to
94 // get all of these; see TextView.java for a good exmaple.
95
96 switch (aID) {
97 // These colors don't seem to be used for anything anymore in Mozilla
98 // (except here at least TextSelectBackground and TextSelectForeground)
99 // The CSS2 colors below are used.
100 case ColorID::WindowBackground:
101 aColor = NS_RGB(0xFF, 0xFF, 0xFF);
102 break;
103 case ColorID::WindowForeground:
104 aColor = mSystemColors.textColorPrimary;
105 break;
106 case ColorID::WidgetBackground:
107 aColor = mSystemColors.colorBackground;
108 break;
109 case ColorID::WidgetForeground:
110 aColor = mSystemColors.colorForeground;
111 break;
112 case ColorID::WidgetSelectBackground:
113 aColor = mSystemColors.textColorHighlight;
114 break;
115 case ColorID::WidgetSelectForeground:
116 aColor = mSystemColors.textColorPrimaryInverse;
117 break;
118 case ColorID::Widget3DHighlight:
119 aColor = LIGHT_GRAY_COLOR;
120 break;
121 case ColorID::Widget3DShadow:
122 aColor = DARK_GRAY_COLOR;
123 break;
124 case ColorID::TextBackground:
125 // not used?
126 aColor = mSystemColors.colorBackground;
127 break;
128 case ColorID::TextForeground:
129 // not used?
130 aColor = mSystemColors.textColorPrimary;
131 break;
132 case ColorID::TextSelectBackground:
133 /* matched to action_accent in java codebase */
134 aColor = NS_RGBA(10, 132, 255, 153);
135 break;
136 case ColorID::TextSelectForeground:
137 aColor = NS_RGB(0, 0, 0);
138 break;
139 case ColorID::IMESelectedRawTextBackground:
140 case ColorID::IMESelectedConvertedTextBackground:
141 // still used
142 aColor = mSystemColors.textColorHighlight;
143 break;
144 case ColorID::IMESelectedRawTextForeground:
145 case ColorID::IMESelectedConvertedTextForeground:
146 // still used
147 aColor = mSystemColors.textColorPrimaryInverse;
148 break;
149 case ColorID::IMERawInputBackground:
150 case ColorID::IMEConvertedTextBackground:
151 aColor = NS_TRANSPARENT;
152 break;
153 case ColorID::IMERawInputForeground:
154 case ColorID::IMEConvertedTextForeground:
155 aColor = NS_SAME_AS_FOREGROUND_COLOR;
156 break;
157 case ColorID::IMERawInputUnderline:
158 case ColorID::IMEConvertedTextUnderline:
159 aColor = NS_SAME_AS_FOREGROUND_COLOR;
160 break;
161 case ColorID::IMESelectedRawTextUnderline:
162 case ColorID::IMESelectedConvertedTextUnderline:
163 aColor = NS_TRANSPARENT;
164 break;
165 case ColorID::SpellCheckerUnderline:
166 aColor = RED_COLOR;
167 break;
168
169 // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
170 case ColorID::Activeborder:
171 // active window border
172 aColor = mSystemColors.colorBackground;
173 break;
174 case ColorID::Activecaption:
175 // active window caption background
176 aColor = mSystemColors.colorBackground;
177 break;
178 case ColorID::Appworkspace:
179 // MDI background color
180 aColor = mSystemColors.colorBackground;
181 break;
182 case ColorID::Background:
183 // desktop background
184 aColor = mSystemColors.colorBackground;
185 break;
186 case ColorID::Graytext:
187 // disabled text in windows, menus, etc.
188 aColor = NS_RGB(0xb1, 0xa5, 0x98);
189 break;
190 case ColorID::MozCellhighlight:
191 case ColorID::MozHtmlCellhighlight:
192 case ColorID::Highlight:
193 case ColorID::MozAccentColor:
194 // background of selected item
195 aColor = NS_RGB(0xfa, 0xd1, 0x84);
196 break;
197 case ColorID::MozCellhighlighttext:
198 case ColorID::MozHtmlCellhighlighttext:
199 case ColorID::Highlighttext:
200 case ColorID::MozAccentColorForeground:
201 case ColorID::Fieldtext:
202 aColor = NS_RGB(0x1a, 0x1a, 0x1a);
203 break;
204 case ColorID::Inactiveborder:
205 // inactive window border
206 aColor = mSystemColors.colorBackground;
207 break;
208 case ColorID::Inactivecaption:
209 // inactive window caption
210 aColor = mSystemColors.colorBackground;
211 break;
212 case ColorID::Inactivecaptiontext:
213 // text in inactive window caption
214 aColor = mSystemColors.textColorTertiary;
215 break;
216 case ColorID::Infobackground:
217 aColor = NS_RGB(0xf5, 0xf5, 0xb5);
218 break;
219 case ColorID::Infotext:
220 aColor = BLACK_COLOR;
221 break;
222 case ColorID::Menu:
223 aColor = NS_RGB(0xf7, 0xf5, 0xf3);
224 break;
225 case ColorID::Scrollbar:
226 // scrollbar gray area
227 aColor = mSystemColors.colorBackground;
228 break;
229
230 case ColorID::Threedface:
231 case ColorID::Buttonface:
232 case ColorID::Threedlightshadow:
233 aColor = NS_RGB(0xec, 0xe7, 0xe2);
234 break;
235
236 case ColorID::Buttonhighlight:
237 case ColorID::Field:
238 case ColorID::Threedhighlight:
239 case ColorID::MozCombobox:
240 case ColorID::MozEventreerow:
241 aColor = NS_RGB(0xff, 0xff, 0xff);
242 break;
243
244 case ColorID::Buttonshadow:
245 case ColorID::Threedshadow:
246 aColor = NS_RGB(0xae, 0xa1, 0x94);
247 break;
248
249 case ColorID::Threeddarkshadow:
250 // 3-D shadow outer edge color
251 aColor = BLACK_COLOR;
252 break;
253
254 case ColorID::MozDialog:
255 case ColorID::Window:
256 case ColorID::Windowframe:
257 aColor = NS_RGB(0xef, 0xeb, 0xe7);
258 break;
259 case ColorID::Buttontext:
260 case ColorID::Captiontext:
261 case ColorID::Menutext:
262 case ColorID::MozButtonhovertext:
263 case ColorID::MozDialogtext:
264 case ColorID::MozComboboxtext:
265 case ColorID::Windowtext:
266 case ColorID::MozColheadertext:
267 case ColorID::MozColheaderhovertext:
268 aColor = NS_RGB(0x10, 0x10, 0x10);
269 break;
270 case ColorID::MozDragtargetzone:
271 aColor = mSystemColors.textColorHighlight;
272 break;
273 case ColorID::MozButtondefault:
274 // default button border color
275 aColor = BLACK_COLOR;
276 break;
277 case ColorID::MozButtonhoverface:
278 aColor = NS_RGB(0xf3, 0xf0, 0xed);
279 break;
280 case ColorID::MozMenuhover:
281 aColor = BG_PRELIGHT_COLOR;
282 break;
283 case ColorID::MozMenuhovertext:
284 aColor = FG_PRELIGHT_COLOR;
285 break;
286 case ColorID::MozOddtreerow:
287 aColor = NS_TRANSPARENT;
288 break;
289 case ColorID::MozNativehyperlinktext:
290 aColor = NS_RGB(0, 0, 0xee);
291 break;
292 case ColorID::MozMenubartext:
293 aColor = mSystemColors.colorForeground;
294 break;
295 case ColorID::MozMenubarhovertext:
296 aColor = FG_PRELIGHT_COLOR;
297 break;
298 default:
299 /* default color is BLACK */
300 aColor = 0;
301 rv = NS_ERROR_FAILURE;
302 break;
303 }
304
305 return rv;
306 }
307
NativeGetInt(IntID aID,int32_t & aResult)308 nsresult nsLookAndFeel::NativeGetInt(IntID aID, int32_t& aResult) {
309 nsresult rv = NS_OK;
310
311 switch (aID) {
312 case IntID::ScrollButtonLeftMouseButtonAction:
313 aResult = 0;
314 break;
315
316 case IntID::ScrollButtonMiddleMouseButtonAction:
317 case IntID::ScrollButtonRightMouseButtonAction:
318 aResult = 3;
319 break;
320
321 case IntID::CaretBlinkTime:
322 aResult = 500;
323 break;
324
325 case IntID::CaretWidth:
326 aResult = 1;
327 break;
328
329 case IntID::ShowCaretDuringSelection:
330 aResult = 0;
331 break;
332
333 case IntID::SelectTextfieldsOnKeyFocus:
334 // Select textfield content when focused by kbd
335 // used by EventStateManager::sTextfieldSelectModel
336 aResult = 1;
337 break;
338
339 case IntID::SubmenuDelay:
340 aResult = 200;
341 break;
342
343 case IntID::TooltipDelay:
344 aResult = 500;
345 break;
346
347 case IntID::MenusCanOverlapOSBar:
348 // we want XUL popups to be able to overlap the task bar.
349 aResult = 1;
350 break;
351
352 case IntID::ScrollArrowStyle:
353 aResult = eScrollArrowStyle_Single;
354 break;
355
356 case IntID::ScrollSliderStyle:
357 aResult = eScrollThumbStyle_Proportional;
358 break;
359
360 case IntID::WindowsDefaultTheme:
361 case IntID::WindowsThemeIdentifier:
362 case IntID::OperatingSystemVersionIdentifier:
363 aResult = 0;
364 rv = NS_ERROR_NOT_IMPLEMENTED;
365 break;
366
367 case IntID::SpellCheckerUnderlineStyle:
368 aResult = NS_STYLE_TEXT_DECORATION_STYLE_WAVY;
369 break;
370
371 case IntID::ScrollbarButtonAutoRepeatBehavior:
372 aResult = 0;
373 break;
374
375 case IntID::ContextMenuOffsetVertical:
376 case IntID::ContextMenuOffsetHorizontal:
377 aResult = 2;
378 break;
379
380 case IntID::PrefersReducedMotion:
381 aResult = java::GeckoSystemStateListener::PrefersReducedMotion();
382 break;
383
384 case IntID::PrimaryPointerCapabilities:
385 aResult = java::GeckoAppShell::GetPrimaryPointerCapabilities();
386 break;
387 case IntID::AllPointerCapabilities:
388 aResult = java::GeckoAppShell::GetAllPointerCapabilities();
389 break;
390
391 case IntID::SystemUsesDarkTheme: {
392 java::GeckoRuntime::LocalRef runtime = java::GeckoRuntime::GetInstance();
393 aResult = runtime && runtime->UsesDarkTheme();
394 break;
395 }
396
397 case IntID::DragThresholdX:
398 case IntID::DragThresholdY:
399 // Threshold where a tap becomes a drag, in 1/240" reference pixels.
400 aResult = 25;
401 break;
402
403 default:
404 aResult = 0;
405 rv = NS_ERROR_FAILURE;
406 }
407
408 return rv;
409 }
410
NativeGetFloat(FloatID aID,float & aResult)411 nsresult nsLookAndFeel::NativeGetFloat(FloatID aID, float& aResult) {
412 nsresult rv = NS_OK;
413
414 switch (aID) {
415 case FloatID::IMEUnderlineRelativeSize:
416 aResult = 1.0f;
417 break;
418
419 case FloatID::SpellCheckerUnderlineRelativeSize:
420 aResult = 1.0f;
421 break;
422
423 default:
424 aResult = -1.0;
425 rv = NS_ERROR_FAILURE;
426 break;
427 }
428 return rv;
429 }
430
431 /*virtual*/
NativeGetFont(FontID aID,nsString & aFontName,gfxFontStyle & aFontStyle)432 bool nsLookAndFeel::NativeGetFont(FontID aID, nsString& aFontName,
433 gfxFontStyle& aFontStyle) {
434 aFontName.AssignLiteral("\"Roboto\"");
435 aFontStyle.style = FontSlantStyle::Normal();
436 aFontStyle.weight = FontWeight::Normal();
437 aFontStyle.stretch = FontStretch::Normal();
438 aFontStyle.size = 9.0 * 96.0f / 72.0f;
439 aFontStyle.systemFont = true;
440 return true;
441 }
442
443 /*virtual*/
GetEchoPasswordImpl()444 bool nsLookAndFeel::GetEchoPasswordImpl() {
445 EnsureInitShowPassword();
446 return mShowPassword;
447 }
448
GetPasswordMaskDelayImpl()449 uint32_t nsLookAndFeel::GetPasswordMaskDelayImpl() {
450 // This value is hard-coded in Android OS's PasswordTransformationMethod.java
451 return 1500;
452 }
453
454 /* virtual */
GetPasswordCharacterImpl()455 char16_t nsLookAndFeel::GetPasswordCharacterImpl() {
456 // This value is hard-coded in Android OS's PasswordTransformationMethod.java
457 return UNICODE_BULLET;
458 }
459
EnsureInitSystemColors()460 void nsLookAndFeel::EnsureInitSystemColors() {
461 if (!mInitializedSystemColors) {
462 mInitializedSystemColors = NS_SUCCEEDED(GetSystemColors());
463 }
464 }
465
EnsureInitShowPassword()466 void nsLookAndFeel::EnsureInitShowPassword() {
467 if (!mInitializedShowPassword && jni::IsAvailable()) {
468 mShowPassword = java::GeckoAppShell::GetShowPasswordSetting();
469 mInitializedShowPassword = true;
470 }
471 }
472