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/. */ 5 6 #ifndef __LookAndFeel 7 #define __LookAndFeel 8 9 #ifndef MOZILLA_INTERNAL_API 10 # error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)." 11 #endif 12 13 #include "nsDebug.h" 14 #include "nsColor.h" 15 #include "nsString.h" 16 #include "nsTArray.h" 17 #include "mozilla/Maybe.h" 18 #include "mozilla/widget/ThemeChangeKind.h" 19 #include "mozilla/ColorScheme.h" 20 21 struct gfxFontStyle; 22 23 class nsIFrame; 24 25 namespace mozilla { 26 27 struct StyleColorSchemeFlags; 28 29 namespace dom { 30 class Document; 31 } 32 33 namespace widget { 34 class FullLookAndFeel; 35 } // namespace widget 36 37 enum class StyleSystemColor : uint8_t; 38 enum class StyleSystemColorScheme : uint8_t; 39 enum class StyleSystemFont : uint8_t; 40 41 class LookAndFeel { 42 public: 43 using ColorID = StyleSystemColor; 44 using ColorScheme = mozilla::ColorScheme; 45 46 // When modifying this list, also modify nsXPLookAndFeel::sIntPrefs 47 // in widget/xpwidgts/nsXPLookAndFeel.cpp. 48 enum class IntID { 49 // default, may be overriden by OS 50 CaretBlinkTime, 51 // Amount of blinks that happen before the caret stops blinking. 52 CaretBlinkCount, 53 // pixel width of caret 54 CaretWidth, 55 // show the caret when text is selected? 56 ShowCaretDuringSelection, 57 // select textfields when focused via tab/accesskey? 58 SelectTextfieldsOnKeyFocus, 59 // delay before submenus open 60 SubmenuDelay, 61 // can popups overlap menu/task bar? 62 MenusCanOverlapOSBar, 63 // should overlay scrollbars be used? 64 UseOverlayScrollbars, 65 // allow H and V overlay scrollbars to overlap? 66 AllowOverlayScrollbarsOverlap, 67 // skip navigating to disabled menu item? 68 SkipNavigatingDisabledMenuItem, 69 // begin a drag if the mouse is moved further than the threshold while the 70 // button is down 71 DragThresholdX, 72 DragThresholdY, 73 // Accessibility theme being used? 74 UseAccessibilityTheme, 75 76 // position of scroll arrows in a scrollbar 77 ScrollArrowStyle, 78 // is scroll thumb proportional or fixed? 79 ScrollSliderStyle, 80 81 // each button can take one of four values: 82 ScrollButtonLeftMouseButtonAction, 83 // 0 - scrolls one line, 1 - scrolls one page 84 ScrollButtonMiddleMouseButtonAction, 85 // 2 - scrolls to end, 3 - button ignored 86 ScrollButtonRightMouseButtonAction, 87 88 // delay for opening spring loaded folders 89 TreeOpenDelay, 90 // delay for closing spring loaded folders 91 TreeCloseDelay, 92 // delay for triggering the tree scrolling 93 TreeLazyScrollDelay, 94 // delay for scrolling the tree 95 TreeScrollDelay, 96 // the maximum number of lines to be scrolled at ones 97 TreeScrollLinesMax, 98 // What type of tab-order to use 99 TabFocusModel, 100 // Should menu items blink when they're chosen? 101 ChosenMenuItemsShouldBlink, 102 103 /* 104 * A Boolean value to determine whether the Windows accent color 105 * should be applied to the title bar. 106 * 107 * The value of this metric is not used on other platforms. These platforms 108 * should return NS_ERROR_NOT_IMPLEMENTED when queried for this metric. 109 */ 110 WindowsAccentColorInTitlebar, 111 112 /* 113 * A Boolean value to determine whether the Windows default theme is 114 * being used. 115 * 116 * The value of this metric is not used on other platforms. These platforms 117 * should return NS_ERROR_NOT_IMPLEMENTED when queried for this metric. 118 */ 119 WindowsDefaultTheme, 120 121 /* 122 * A Boolean value to determine whether the DWM compositor is being used 123 * 124 * This metric is not used on non-Windows platforms. These platforms 125 * should return NS_ERROR_NOT_IMPLEMENTED when queried for this metric. 126 */ 127 DWMCompositor, 128 129 /* 130 * A Boolean value to determine whether Windows is themed (Classic vs. 131 * uxtheme) 132 * 133 * This is Windows-specific and is not implemented on other platforms 134 * (will return the default of NS_ERROR_FAILURE). 135 */ 136 WindowsClassic, 137 138 /* 139 * A Boolean value to determine whether the current Windows desktop theme 140 * supports Aero Glass. 141 * 142 * This is Windows-specific and is not implemented on other platforms 143 * (will return the default of NS_ERROR_FAILURE). 144 */ 145 WindowsGlass, 146 147 /* 148 * A Boolean value to determine whether the Mac graphite theme is 149 * being used. 150 */ 151 MacGraphiteTheme, 152 153 /* 154 * A Boolean value to determine whether the macOS Big Sur-specific 155 * theming should be used. 156 */ 157 MacBigSurTheme, 158 159 /* 160 * A Boolean value to determine whether macOS is in RTL mode or not. 161 */ 162 MacRTL, 163 164 /* 165 * AlertNotificationOrigin indicates from which corner of the 166 * screen alerts slide in, and from which direction (horizontal/vertical). 167 * 0, the default, represents bottom right, sliding vertically. 168 * Use any bitwise combination of the following constants: 169 * NS_ALERT_HORIZONTAL (1), NS_ALERT_LEFT (2), NS_ALERT_TOP (4). 170 * 171 * 6 4 172 * +-----------+ 173 * 7| |5 174 * | | 175 * 3| |1 176 * +-----------+ 177 * 2 0 178 */ 179 AlertNotificationOrigin, 180 181 /** 182 * If true, clicking on a scrollbar (not as in dragging the thumb) defaults 183 * to scrolling the view corresponding to the clicked point. Otherwise, we 184 * only do so if the scrollbar is clicked using the middle mouse button or 185 * if shift is pressed when the scrollbar is clicked. 186 */ 187 ScrollToClick, 188 189 /** 190 * IME and spell checker underline styles, the values should be 191 * NS_DECORATION_LINE_STYLE_*. They are defined below. 192 */ 193 IMERawInputUnderlineStyle, 194 IMESelectedRawTextUnderlineStyle, 195 IMEConvertedTextUnderlineStyle, 196 IMESelectedConvertedTextUnderline, 197 SpellCheckerUnderlineStyle, 198 199 /** 200 * If this metric != 0, support window dragging on the menubar. 201 */ 202 MenuBarDrag, 203 /** 204 * 0: scrollbar button repeats to scroll only when cursor is on the button. 205 * 1: scrollbar button repeats to scroll even if cursor is outside of it. 206 */ 207 ScrollbarButtonAutoRepeatBehavior, 208 /** 209 * Delay before showing a tooltip. 210 */ 211 TooltipDelay, 212 /* 213 * A Boolean value to determine whether swipe animations should be used. 214 */ 215 SwipeAnimationEnabled, 216 217 /* 218 * Controls whether overlay scrollbars display when the user moves 219 * the mouse in a scrollable frame. 220 */ 221 ScrollbarDisplayOnMouseMove, 222 223 /* 224 * Overlay scrollbar animation constants. 225 */ 226 ScrollbarFadeBeginDelay, 227 ScrollbarFadeDuration, 228 229 /** 230 * Distance in pixels to offset the context menu from the cursor 231 * on open. 232 */ 233 ContextMenuOffsetVertical, 234 ContextMenuOffsetHorizontal, 235 236 /* 237 * A boolean value indicating whether client-side decorations are 238 * supported by the user's GTK version. 239 */ 240 GTKCSDAvailable, 241 242 /* 243 * A boolean value indicating whether client-side decorations should 244 * contain a minimize button. 245 */ 246 GTKCSDMinimizeButton, 247 248 /* 249 * A boolean value indicating whether client-side decorations should 250 * contain a maximize button. 251 */ 252 GTKCSDMaximizeButton, 253 254 /* 255 * A boolean value indicating whether client-side decorations should 256 * contain a close button. 257 */ 258 GTKCSDCloseButton, 259 260 /** 261 * An Integer value that will represent the position of the Minimize button 262 * in GTK Client side decoration header. 263 */ 264 GTKCSDMinimizeButtonPosition, 265 266 /** 267 * An Integer value that will represent the position of the Maximize button 268 * in GTK Client side decoration header. 269 */ 270 GTKCSDMaximizeButtonPosition, 271 272 /** 273 * An Integer value that will represent the position of the Close button 274 * in GTK Client side decoration header. 275 */ 276 GTKCSDCloseButtonPosition, 277 278 /* 279 * A boolean value indicating whether titlebar buttons are located 280 * in left titlebar corner. 281 */ 282 GTKCSDReversedPlacement, 283 284 /* 285 * A boolean value indicating whether or not the OS is using a dark theme, 286 * which we may want to switch to as well if not overridden by the user. 287 */ 288 SystemUsesDarkTheme, 289 290 /** 291 * Corresponding to prefers-reduced-motion. 292 * https://drafts.csswg.org/mediaqueries-5/#prefers-reduced-motion 293 * 0: no-preference 294 * 1: reduce 295 */ 296 297 PrefersReducedMotion, 298 /** 299 * Corresponding to PointerCapabilities in ServoTypes.h 300 * 0: None 301 * 1: Coarse 302 * 2: Fine 303 * 4: Hover 304 */ 305 PrimaryPointerCapabilities, 306 /** 307 * Corresponding to union of PointerCapabilities values in ServoTypes.h 308 * E.g. if there is a mouse and a digitizer, the value will be 309 * 'Coarse | Fine | Hover'. 310 */ 311 AllPointerCapabilities, 312 /** The vertical scrollbar width, in CSS pixels. */ 313 SystemVerticalScrollbarWidth, 314 315 /** The horizontal scrollbar height, in CSS pixels. */ 316 SystemHorizontalScrollbarHeight, 317 318 /** A boolean value to determine whether a touch device is present */ 319 TouchDeviceSupportPresent, 320 321 /** GTK titlebar radius */ 322 TitlebarRadius, 323 324 /** GTK menu radius */ 325 GtkMenuRadius, 326 327 /* 328 * Not an ID; used to define the range of valid IDs. Must be last. 329 */ 330 End, 331 }; 332 333 // This is a common enough integer that seems worth the shortcut. UseOverlayScrollbars()334 static bool UseOverlayScrollbars() { 335 return GetInt(IntID::UseOverlayScrollbars); 336 } 337 338 enum { 339 eScrollArrow_None = 0, 340 eScrollArrow_StartBackward = 0x1000, 341 eScrollArrow_StartForward = 0x0100, 342 eScrollArrow_EndBackward = 0x0010, 343 eScrollArrow_EndForward = 0x0001 344 }; 345 346 enum { 347 // single arrow at each end 348 eScrollArrowStyle_Single = 349 eScrollArrow_StartBackward | eScrollArrow_EndForward, 350 // both arrows at bottom/right, none at top/left 351 eScrollArrowStyle_BothAtBottom = 352 eScrollArrow_EndBackward | eScrollArrow_EndForward, 353 // both arrows at both ends 354 eScrollArrowStyle_BothAtEachEnd = 355 eScrollArrow_EndBackward | eScrollArrow_EndForward | 356 eScrollArrow_StartBackward | eScrollArrow_StartForward, 357 // both arrows at top/left, none at bottom/right 358 eScrollArrowStyle_BothAtTop = 359 eScrollArrow_StartBackward | eScrollArrow_StartForward 360 }; 361 362 enum { eScrollThumbStyle_Normal, eScrollThumbStyle_Proportional }; 363 364 // When modifying this list, also modify nsXPLookAndFeel::sFloatPrefs 365 // in widget/nsXPLookAndFeel.cpp. 366 enum class FloatID { 367 IMEUnderlineRelativeSize, 368 SpellCheckerUnderlineRelativeSize, 369 370 // The width/height ratio of the cursor. If used, the CaretWidth int metric 371 // should be added to the calculated caret width. 372 CaretAspectRatio, 373 374 // GTK text scale factor. 375 TextScaleFactor, 376 377 // Mouse pointer scaling factor. 378 CursorScale, 379 380 // Not an ID; used to define the range of valid IDs. Must be last. 381 End, 382 }; 383 384 using FontID = mozilla::StyleSystemFont; 385 SystemColorScheme()386 static ColorScheme SystemColorScheme() { 387 return GetInt(IntID::SystemUsesDarkTheme) ? ColorScheme::Dark 388 : ColorScheme::Light; 389 } 390 391 enum class ChromeColorSchemeSetting { Light, Dark, System }; 392 static ChromeColorSchemeSetting ColorSchemeSettingForChrome(); 393 static ColorScheme ThemeDerivedColorSchemeForContent(); 394 ColorSchemeForChrome()395 static ColorScheme ColorSchemeForChrome() { 396 MOZ_ASSERT(sColorSchemeInitialized); 397 return sChromeColorScheme; 398 } PreferredColorSchemeForContent()399 static ColorScheme PreferredColorSchemeForContent() { 400 MOZ_ASSERT(sColorSchemeInitialized); 401 return sContentColorScheme; 402 } 403 404 static ColorScheme ColorSchemeForStyle(const dom::Document&, 405 const StyleColorSchemeFlags&); 406 static ColorScheme ColorSchemeForFrame(const nsIFrame*); 407 408 // Whether standins for native colors should be used (that is, colors faked, 409 // taken from win7, mostly). This forces light appearance, effectively. 410 enum class UseStandins : bool { No, Yes }; 411 static UseStandins ShouldUseStandins(const dom::Document&, ColorID); 412 413 // Returns a native color value (might be overwritten by prefs) for a given 414 // color id. 415 // 416 // NOTE: 417 // ColorID::TextSelectForeground might return NS_SAME_AS_FOREGROUND_COLOR. 418 // ColorID::IME* might return NS_TRANSPARENT, NS_SAME_AS_FOREGROUND_COLOR or 419 // NS_40PERCENT_FOREGROUND_COLOR. 420 // These values have particular meaning. Then, they are not an actual 421 // color value. 422 static Maybe<nscolor> GetColor(ColorID, ColorScheme, UseStandins); 423 424 // Gets the color with appropriate defaults for UseStandins, ColorScheme etc 425 // for a given frame. 426 static Maybe<nscolor> GetColor(ColorID, const nsIFrame*); 427 428 // Versions of the above which returns the color if found, or a default (which 429 // defaults to opaque black) otherwise. 430 static nscolor Color(ColorID aId, ColorScheme aScheme, 431 UseStandins aUseStandins, 432 nscolor aDefault = NS_RGB(0, 0, 0)) { 433 return GetColor(aId, aScheme, aUseStandins).valueOr(aDefault); 434 } 435 436 static nscolor Color(ColorID aId, nsIFrame* aFrame, 437 nscolor aDefault = NS_RGB(0, 0, 0)) { 438 return GetColor(aId, aFrame).valueOr(aDefault); 439 } 440 441 /** 442 * GetInt() and GetFloat() return a int or float value for aID. The result 443 * might be distance, time, some flags or a int value which has particular 444 * meaning. See each document at definition of each ID for the detail. 445 * The result is always 0 when they return error. Therefore, if you want to 446 * use a value for the default value, you should use the other method which 447 * returns int or float directly. 448 */ 449 static nsresult GetInt(IntID, int32_t* aResult); 450 static nsresult GetFloat(FloatID aID, float* aResult); 451 452 static int32_t GetInt(IntID aID, int32_t aDefault = 0) { 453 int32_t result; 454 if (NS_FAILED(GetInt(aID, &result))) { 455 return aDefault; 456 } 457 return result; 458 } 459 460 static float GetFloat(FloatID aID, float aDefault = 0.0f) { 461 float result; 462 if (NS_FAILED(GetFloat(aID, &result))) { 463 return aDefault; 464 } 465 return result; 466 } 467 468 /** 469 * Retrieve the name and style of a system-theme font. Returns true 470 * if the system theme specifies this font, false if a default should 471 * be used. In the latter case neither aName nor aStyle is modified. 472 * 473 * Size of the font should be in CSS pixels, not device pixels. 474 * 475 * @param aID Which system-theme font is wanted. 476 * @param aName The name of the font to use. 477 * @param aStyle Styling to apply to the font. 478 */ 479 static bool GetFont(FontID aID, nsString& aName, gfxFontStyle& aStyle); 480 481 /** 482 * GetPasswordCharacter() returns a unicode character which should be used 483 * for a masked character in password editor. E.g., '*'. 484 */ 485 static char16_t GetPasswordCharacter(); 486 487 /** 488 * If the latest character in password field shouldn't be hidden by the 489 * result of GetPasswordCharacter(), GetEchoPassword() returns TRUE. 490 * Otherwise, FALSE. 491 */ 492 static bool GetEchoPassword(); 493 494 /** 495 * Whether we should be drawing in the titlebar by default. 496 */ 497 static bool DrawInTitlebar(); 498 499 /** 500 * The millisecond to mask password value. 501 * This value is only valid when GetEchoPassword() returns true. 502 */ 503 static uint32_t GetPasswordMaskDelay(); 504 505 /** Gets theme information for about:support */ 506 static void GetThemeInfo(nsACString&); 507 508 /** 509 * When system look and feel is changed, Refresh() must be called. Then, 510 * cached data would be released. 511 */ 512 static void Refresh(); 513 514 /** 515 * GTK's initialization code can't be run off main thread, call this 516 * if you plan on using LookAndFeel off main thread later. 517 * 518 * This initialized state may get reset due to theme changes, so it 519 * must be called prior to each potential off-main-thread LookAndFeel 520 * call, not just once. 521 */ 522 static void NativeInit(); 523 524 static void SetData(widget::FullLookAndFeel&& aTables); 525 static void NotifyChangedAllWindows(widget::ThemeChangeKind); HasPendingGlobalThemeChange()526 static bool HasPendingGlobalThemeChange() { return sGlobalThemeChanged; } HandleGlobalThemeChange()527 static void HandleGlobalThemeChange() { 528 if (MOZ_UNLIKELY(HasPendingGlobalThemeChange())) { 529 DoHandleGlobalThemeChange(); 530 } 531 } EnsureColorSchemesInitialized()532 static void EnsureColorSchemesInitialized() { 533 if (!sColorSchemeInitialized) { 534 RecomputeColorSchemes(); 535 } 536 MOZ_ASSERT(sColorSchemeInitialized); 537 } 538 539 static ColorScheme sChromeColorScheme; 540 static ColorScheme sContentColorScheme; 541 542 protected: 543 static void RecomputeColorSchemes(); 544 static bool sColorSchemeInitialized; 545 546 static void DoHandleGlobalThemeChange(); 547 // Set to true when ThemeChanged needs to be called on mTheme (and other 548 // global LookAndFeel. This is used because mTheme is a service, so there's 549 // no need to notify it from more than one prescontext. 550 static bool sGlobalThemeChanged; 551 }; 552 553 } // namespace mozilla 554 555 // --------------------------------------------------------------------- 556 // Special colors for ColorID::IME* and ColorID::SpellCheckerUnderline 557 // --------------------------------------------------------------------- 558 559 // For background color only. 560 constexpr nscolor NS_TRANSPARENT = NS_RGBA(0x01, 0x00, 0x00, 0x00); 561 // For foreground color only. 562 constexpr nscolor NS_SAME_AS_FOREGROUND_COLOR = NS_RGBA(0x02, 0x00, 0x00, 0x00); 563 constexpr nscolor NS_40PERCENT_FOREGROUND_COLOR = 564 NS_RGBA(0x03, 0x00, 0x00, 0x00); 565 566 #define NS_IS_SELECTION_SPECIAL_COLOR(c) \ 567 ((c) == NS_TRANSPARENT || (c) == NS_SAME_AS_FOREGROUND_COLOR || \ 568 (c) == NS_40PERCENT_FOREGROUND_COLOR) 569 570 // ------------------------------------------ 571 // Bits for IntID::AlertNotificationOrigin 572 // ------------------------------------------ 573 574 #define NS_ALERT_HORIZONTAL 1 575 #define NS_ALERT_LEFT 2 576 #define NS_ALERT_TOP 4 577 578 #endif /* __LookAndFeel */ 579