#![cfg(feature = "parser")]
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
use crate::{
corety::{AzString, OptionF32, OptionString, OptionU16},
css::Css,
parser2::{new_from_str, CssParseWarnMsg},
props::{
basic::{
color::{parse_css_color, ColorU, OptionColorU},
pixel::{PixelValue, OptionPixelValue},
},
style::scrollbar::{ComputedScrollbarStyle, OverscrollBehavior, ScrollBehavior, ScrollPhysics},
},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RicingMode {
Off,
Default,
Force,
}
impl Default for RicingMode {
fn default() -> Self { RicingMode::Default }
}
pub fn ricing_mode() -> RicingMode {
let raw = match std::env::var("AZ_RICING") {
Ok(s) => s,
Err(_) => return RicingMode::Default,
};
match raw.trim().to_ascii_lowercase().as_str() {
"off" | "disabled" | "none" | "0" | "false" => RicingMode::Off,
"force" | "prefer" | "aggressive" | "1" | "true" => RicingMode::Force,
_ => RicingMode::Default,
}
}
pub fn ricing_enabled() -> bool {
!matches!(ricing_mode(), RicingMode::Off)
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[repr(C, u8)]
pub enum Platform {
Windows,
MacOs,
Linux(DesktopEnvironment),
Android,
Ios,
#[default]
Unknown,
}
impl Platform {
#[inline]
pub fn current() -> Self {
#[cfg(target_os = "macos")]
{ Platform::MacOs }
#[cfg(target_os = "windows")]
{ Platform::Windows }
#[cfg(target_os = "linux")]
{ Platform::Linux(DesktopEnvironment::Other(AzString::from_const_str("unknown"))) }
#[cfg(target_os = "android")]
{ Platform::Android }
#[cfg(target_os = "ios")]
{ Platform::Ios }
#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux", target_os = "android", target_os = "ios")))]
{ Platform::Unknown }
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[repr(C, u8)]
pub enum DesktopEnvironment {
Gnome,
Kde,
Other(AzString),
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum Theme {
#[default]
Light,
Dark,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct SystemStyle {
pub fonts: SystemFonts,
pub metrics: SystemMetrics,
pub linux: LinuxCustomization,
pub platform: Platform,
pub focus_visuals: FocusVisuals,
pub language: AzString,
pub app_specific_stylesheet: Option<Box<Css>>,
pub scrollbar: Option<Box<ComputedScrollbarStyle>>,
pub scroll_physics: ScrollPhysics,
pub theme: Theme,
pub os_version: crate::dynamic_selector::OsVersion,
pub prefers_reduced_motion: crate::dynamic_selector::BoolCondition,
pub prefers_high_contrast: crate::dynamic_selector::BoolCondition,
pub accessibility: AccessibilitySettings,
pub input: InputMetrics,
pub text_rendering: TextRenderingHints,
pub scrollbar_preferences: ScrollbarPreferences,
pub visual_hints: VisualHints,
pub animation: AnimationMetrics,
pub colors: SystemColors,
pub icon_style: IconStyleOptions,
pub audio: AudioMetrics,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct IconStyleOptions {
pub prefer_grayscale: bool,
pub tint_color: OptionColorU,
pub inherit_text_color: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
#[derive(Default)]
pub enum SystemFontType {
#[default]
Ui,
UiBold,
Monospace,
MonospaceBold,
MonospaceItalic,
Title,
TitleBold,
Menu,
Small,
Serif,
SerifBold,
}
impl SystemFontType {
pub fn from_css_str(s: &str) -> Option<Self> {
let s = s.trim();
if !s.starts_with("system:") {
return None;
}
let rest = &s[7..]; match rest {
"ui" => Some(SystemFontType::Ui),
"ui:bold" => Some(SystemFontType::UiBold),
"monospace" => Some(SystemFontType::Monospace),
"monospace:bold" => Some(SystemFontType::MonospaceBold),
"monospace:italic" => Some(SystemFontType::MonospaceItalic),
"title" => Some(SystemFontType::Title),
"title:bold" => Some(SystemFontType::TitleBold),
"menu" => Some(SystemFontType::Menu),
"small" => Some(SystemFontType::Small),
"serif" => Some(SystemFontType::Serif),
"serif:bold" => Some(SystemFontType::SerifBold),
_ => None,
}
}
pub fn as_css_str(&self) -> &'static str {
match self {
SystemFontType::Ui => "system:ui",
SystemFontType::UiBold => "system:ui:bold",
SystemFontType::Monospace => "system:monospace",
SystemFontType::MonospaceBold => "system:monospace:bold",
SystemFontType::MonospaceItalic => "system:monospace:italic",
SystemFontType::Title => "system:title",
SystemFontType::TitleBold => "system:title:bold",
SystemFontType::Menu => "system:menu",
SystemFontType::Small => "system:small",
SystemFontType::Serif => "system:serif",
SystemFontType::SerifBold => "system:serif:bold",
}
}
pub fn is_bold(&self) -> bool {
matches!(
self,
SystemFontType::UiBold
| SystemFontType::MonospaceBold
| SystemFontType::TitleBold
| SystemFontType::SerifBold
)
}
pub fn is_italic(&self) -> bool {
matches!(self, SystemFontType::MonospaceItalic)
}
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct AccessibilitySettings {
pub text_scale_factor: f32,
pub prefers_bold_text: bool,
pub prefers_larger_text: bool,
pub prefers_high_contrast: bool,
pub prefers_reduced_motion: bool,
pub prefers_reduced_transparency: bool,
pub screen_reader_active: bool,
pub differentiate_without_color: bool,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct SystemColors {
pub text: OptionColorU,
pub secondary_text: OptionColorU,
pub tertiary_text: OptionColorU,
pub background: OptionColorU,
pub accent: OptionColorU,
pub accent_text: OptionColorU,
pub button_face: OptionColorU,
pub button_text: OptionColorU,
pub disabled_text: OptionColorU,
pub window_background: OptionColorU,
pub under_page_background: OptionColorU,
pub selection_background: OptionColorU,
pub selection_text: OptionColorU,
pub selection_background_inactive: OptionColorU,
pub selection_text_inactive: OptionColorU,
pub link: OptionColorU,
pub separator: OptionColorU,
pub grid: OptionColorU,
pub find_highlight: OptionColorU,
pub sidebar_background: OptionColorU,
pub sidebar_selection: OptionColorU,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct SystemFonts {
pub ui_font: OptionString,
pub ui_font_size: OptionF32,
pub monospace_font: OptionString,
pub monospace_font_size: OptionF32,
pub ui_font_bold: OptionString,
pub title_font: OptionString,
pub title_font_size: OptionF32,
pub menu_font: OptionString,
pub menu_font_size: OptionF32,
pub small_font: OptionString,
pub small_font_size: OptionF32,
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct SystemMetrics {
pub corner_radius: OptionPixelValue,
pub border_width: OptionPixelValue,
pub button_padding_horizontal: OptionPixelValue,
pub button_padding_vertical: OptionPixelValue,
pub titlebar: TitlebarMetrics,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
#[repr(C)]
pub enum TitlebarButtonSide {
Left,
#[default]
Right,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct TitlebarButtons {
pub has_close: bool,
pub has_minimize: bool,
pub has_maximize: bool,
pub has_fullscreen: bool,
}
impl Default for TitlebarButtons {
fn default() -> Self {
Self {
has_close: true,
has_minimize: true,
has_maximize: true,
has_fullscreen: false,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct SafeAreaInsets {
pub top: OptionPixelValue,
pub bottom: OptionPixelValue,
pub left: OptionPixelValue,
pub right: OptionPixelValue,
}
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub struct TitlebarMetrics {
pub button_side: TitlebarButtonSide,
pub buttons: TitlebarButtons,
pub height: OptionPixelValue,
pub button_area_width: OptionPixelValue,
pub padding_horizontal: OptionPixelValue,
pub safe_area: SafeAreaInsets,
pub title_font: OptionString,
pub title_font_size: OptionF32,
pub title_font_weight: OptionU16,
}
impl Default for TitlebarMetrics {
fn default() -> Self {
Self {
button_side: TitlebarButtonSide::Right,
buttons: TitlebarButtons::default(),
height: OptionPixelValue::Some(PixelValue::px(32.0)),
button_area_width: OptionPixelValue::Some(PixelValue::px(100.0)),
padding_horizontal: OptionPixelValue::Some(PixelValue::px(8.0)),
safe_area: SafeAreaInsets::default(),
title_font: OptionString::None,
title_font_size: OptionF32::Some(13.0),
title_font_weight: OptionU16::Some(600), }
}
}
impl TitlebarMetrics {
pub fn windows() -> Self {
Self {
button_side: TitlebarButtonSide::Right,
buttons: TitlebarButtons {
has_close: true,
has_minimize: true,
has_maximize: true,
has_fullscreen: false,
},
height: OptionPixelValue::Some(PixelValue::px(32.0)),
button_area_width: OptionPixelValue::Some(PixelValue::px(138.0)), padding_horizontal: OptionPixelValue::Some(PixelValue::px(8.0)),
safe_area: SafeAreaInsets::default(),
title_font: OptionString::Some("Segoe UI Variable Text".into()),
title_font_size: OptionF32::Some(12.0),
title_font_weight: OptionU16::Some(400), }
}
pub fn macos() -> Self {
Self {
button_side: TitlebarButtonSide::Left,
buttons: TitlebarButtons {
has_close: true,
has_minimize: true,
has_maximize: false, has_fullscreen: true,
},
height: OptionPixelValue::Some(PixelValue::px(28.0)),
button_area_width: OptionPixelValue::Some(PixelValue::px(78.0)), padding_horizontal: OptionPixelValue::Some(PixelValue::px(8.0)),
safe_area: SafeAreaInsets::default(),
title_font: OptionString::Some(".SF NS".into()),
title_font_size: OptionF32::Some(13.0),
title_font_weight: OptionU16::Some(600), }
}
pub fn linux_gnome() -> Self {
Self {
button_side: TitlebarButtonSide::Right, buttons: TitlebarButtons {
has_close: true,
has_minimize: true,
has_maximize: true,
has_fullscreen: false,
},
height: OptionPixelValue::Some(PixelValue::px(35.0)),
button_area_width: OptionPixelValue::Some(PixelValue::px(100.0)),
padding_horizontal: OptionPixelValue::Some(PixelValue::px(12.0)),
safe_area: SafeAreaInsets::default(),
title_font: OptionString::Some("Cantarell".into()),
title_font_size: OptionF32::Some(11.0),
title_font_weight: OptionU16::Some(700), }
}
pub fn ios() -> Self {
Self {
button_side: TitlebarButtonSide::Left,
buttons: TitlebarButtons {
has_close: false, has_minimize: false,
has_maximize: false,
has_fullscreen: false,
},
height: OptionPixelValue::Some(PixelValue::px(44.0)),
button_area_width: OptionPixelValue::Some(PixelValue::px(0.0)),
padding_horizontal: OptionPixelValue::Some(PixelValue::px(16.0)),
safe_area: SafeAreaInsets {
top: OptionPixelValue::Some(PixelValue::px(47.0)),
bottom: OptionPixelValue::Some(PixelValue::px(34.0)),
left: OptionPixelValue::None,
right: OptionPixelValue::None,
},
title_font: OptionString::Some(".SFUI-Semibold".into()),
title_font_size: OptionF32::Some(17.0),
title_font_weight: OptionU16::Some(600),
}
}
pub fn android() -> Self {
Self {
button_side: TitlebarButtonSide::Left, buttons: TitlebarButtons {
has_close: false,
has_minimize: false,
has_maximize: false,
has_fullscreen: false,
},
height: OptionPixelValue::Some(PixelValue::px(56.0)),
button_area_width: OptionPixelValue::Some(PixelValue::px(48.0)), padding_horizontal: OptionPixelValue::Some(PixelValue::px(16.0)),
safe_area: SafeAreaInsets::default(),
title_font: OptionString::Some("Roboto Medium".into()),
title_font_size: OptionF32::Some(20.0),
title_font_weight: OptionU16::Some(500),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct InputMetrics {
pub double_click_time_ms: u32,
pub double_click_distance_px: f32,
pub drag_threshold_px: f32,
pub caret_blink_rate_ms: u32,
pub caret_width_px: f32,
pub wheel_scroll_lines: u32,
pub hover_time_ms: u32,
}
impl Default for InputMetrics {
fn default() -> Self {
Self {
double_click_time_ms: 500,
double_click_distance_px: 4.0,
drag_threshold_px: 5.0,
caret_blink_rate_ms: 530,
caret_width_px: 1.0,
wheel_scroll_lines: 3,
hover_time_ms: 400,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum SubpixelType {
#[default]
None,
Rgb,
Bgr,
VRgb,
VBgr,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct TextRenderingHints {
pub subpixel_type: SubpixelType,
pub font_smoothing_gamma: u32,
pub font_smoothing_enabled: bool,
pub increased_contrast: bool,
}
impl Default for TextRenderingHints {
fn default() -> Self {
Self {
subpixel_type: SubpixelType::None,
font_smoothing_gamma: 1000,
font_smoothing_enabled: true,
increased_contrast: false,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct FocusVisuals {
pub focus_ring_color: OptionColorU,
pub focus_border_width: OptionPixelValue,
pub focus_border_height: OptionPixelValue,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum ScrollbarVisibility {
Always,
#[default]
WhenScrolling,
Automatic,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum ScrollbarTrackClick {
JumpToPosition,
#[default]
PageUpDown,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct ScrollbarPreferences {
pub visibility: ScrollbarVisibility,
pub track_click: ScrollbarTrackClick,
}
impl Default for ScrollbarPreferences {
fn default() -> Self {
Self {
visibility: ScrollbarVisibility::WhenScrolling,
track_click: ScrollbarTrackClick::PageUpDown,
}
}
}
#[derive(Debug, Default, Clone, PartialEq)]
#[repr(C)]
pub struct LinuxCustomization {
pub gtk_theme: OptionString,
pub icon_theme: OptionString,
pub cursor_theme: OptionString,
pub cursor_size: u32,
pub titlebar_button_layout: OptionString,
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum ToolbarStyle {
#[default]
IconsOnly,
TextOnly,
TextBesideIcon,
TextBelowIcon,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct VisualHints {
pub toolbar_style: ToolbarStyle,
pub show_button_images: bool,
pub show_menu_images: bool,
pub show_tooltips: bool,
pub flash_on_alert: bool,
}
impl Default for VisualHints {
fn default() -> Self {
Self {
toolbar_style: ToolbarStyle::IconsOnly,
show_button_images: false,
show_menu_images: true,
show_tooltips: true,
flash_on_alert: true,
}
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum FocusBehavior {
#[default]
AlwaysVisible,
KeyboardOnly,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct AnimationMetrics {
pub animations_enabled: bool,
pub animation_duration_factor: f32,
pub focus_indicator_behavior: FocusBehavior,
}
impl Default for AnimationMetrics {
fn default() -> Self {
Self {
animations_enabled: true,
animation_duration_factor: 1.0,
focus_indicator_behavior: FocusBehavior::AlwaysVisible,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub struct AudioMetrics {
pub event_sounds_enabled: bool,
pub input_feedback_sounds_enabled: bool,
}
impl Default for AudioMetrics {
fn default() -> Self {
Self {
event_sounds_enabled: true,
input_feedback_sounds_enabled: false,
}
}
}
pub mod apple_fonts {
pub const SYSTEM_FONT: &str = "System Font";
pub const SF_NS_ROUNDED: &str = "SF NS Rounded";
pub const SF_COMPACT: &str = "SF Compact";
pub const SF_MONO: &str = "SF NS Mono Light";
pub const NEW_YORK: &str = "New York";
pub const SF_ARABIC: &str = "SF Arabic";
pub const SF_ARMENIAN: &str = "SF Armenian";
pub const SF_GEORGIAN: &str = "SF Georgian";
pub const SF_HEBREW: &str = "SF Hebrew";
pub const MENLO: &str = "Menlo";
pub const MENLO_REGULAR: &str = "Menlo Regular";
pub const MENLO_BOLD: &str = "Menlo Bold";
pub const MONACO: &str = "Monaco";
pub const LUCIDA_GRANDE: &str = "Lucida Grande";
pub const LUCIDA_GRANDE_BOLD: &str = "Lucida Grande Bold";
pub const HELVETICA_NEUE: &str = "Helvetica Neue";
pub const HELVETICA_NEUE_BOLD: &str = "Helvetica Neue Bold";
}
pub mod windows_fonts {
pub const SEGOE_UI_VARIABLE: &str = "Segoe UI Variable";
pub const SEGOE_UI_VARIABLE_TEXT: &str = "Segoe UI Variable Text";
pub const SEGOE_UI_VARIABLE_DISPLAY: &str = "Segoe UI Variable Display";
pub const SEGOE_UI: &str = "Segoe UI";
pub const CONSOLAS: &str = "Consolas";
pub const CASCADIA_CODE: &str = "Cascadia Code";
pub const CASCADIA_MONO: &str = "Cascadia Mono";
pub const TAHOMA: &str = "Tahoma";
pub const MS_SANS_SERIF: &str = "MS Sans Serif";
pub const LUCIDA_CONSOLE: &str = "Lucida Console";
pub const COURIER_NEW: &str = "Courier New";
}
pub mod linux_fonts {
pub const CANTARELL: &str = "Cantarell";
pub const ADWAITA: &str = "Adwaita";
pub const UBUNTU: &str = "Ubuntu";
pub const UBUNTU_MONO: &str = "Ubuntu Mono";
pub const DEJAVU_SANS: &str = "DejaVu Sans";
pub const DEJAVU_SANS_MONO: &str = "DejaVu Sans Mono";
pub const DEJAVU_SERIF: &str = "DejaVu Serif";
pub const LIBERATION_SANS: &str = "Liberation Sans";
pub const LIBERATION_MONO: &str = "Liberation Mono";
pub const LIBERATION_SERIF: &str = "Liberation Serif";
pub const NOTO_SANS: &str = "Noto Sans";
pub const NOTO_MONO: &str = "Noto Sans Mono";
pub const NOTO_SERIF: &str = "Noto Serif";
pub const HACK: &str = "Hack";
pub const MONOSPACE: &str = "Monospace";
pub const SANS_SERIF: &str = "Sans";
pub const SERIF: &str = "Serif";
}
impl SystemFontType {
pub fn get_fallback_chain(&self, platform: &Platform) -> Vec<&'static str> {
match platform {
Platform::MacOs | Platform::Ios => self.macos_fallback_chain(),
Platform::Windows => self.windows_fallback_chain(),
Platform::Linux(_) => self.linux_fallback_chain(),
Platform::Android => self.android_fallback_chain(),
Platform::Unknown => self.generic_fallback_chain(),
}
}
fn macos_fallback_chain(&self) -> Vec<&'static str> {
match self {
SystemFontType::Ui => vec![
apple_fonts::SYSTEM_FONT,
apple_fonts::HELVETICA_NEUE,
apple_fonts::LUCIDA_GRANDE,
],
SystemFontType::UiBold => vec![
apple_fonts::HELVETICA_NEUE, apple_fonts::LUCIDA_GRANDE,
],
SystemFontType::Monospace => vec![
apple_fonts::MENLO,
apple_fonts::MONACO,
],
SystemFontType::MonospaceBold | SystemFontType::MonospaceItalic => vec![
apple_fonts::MENLO, apple_fonts::MONACO,
],
SystemFontType::Title => vec![
apple_fonts::SYSTEM_FONT,
apple_fonts::HELVETICA_NEUE,
],
SystemFontType::TitleBold => vec![
apple_fonts::HELVETICA_NEUE, apple_fonts::LUCIDA_GRANDE,
],
SystemFontType::Menu => vec![
apple_fonts::SYSTEM_FONT,
apple_fonts::HELVETICA_NEUE,
],
SystemFontType::Small => vec![
apple_fonts::SYSTEM_FONT,
apple_fonts::HELVETICA_NEUE,
],
SystemFontType::Serif => vec![
apple_fonts::NEW_YORK,
"Georgia",
"Times New Roman",
],
SystemFontType::SerifBold => vec![
"Georgia", "Times New Roman",
],
}
}
fn windows_fallback_chain(&self) -> Vec<&'static str> {
match self {
SystemFontType::Ui | SystemFontType::UiBold => vec![
windows_fonts::SEGOE_UI_VARIABLE_TEXT,
windows_fonts::SEGOE_UI,
windows_fonts::TAHOMA,
],
SystemFontType::Monospace | SystemFontType::MonospaceBold | SystemFontType::MonospaceItalic => vec![
windows_fonts::CASCADIA_MONO,
windows_fonts::CASCADIA_CODE,
windows_fonts::CONSOLAS,
windows_fonts::LUCIDA_CONSOLE,
windows_fonts::COURIER_NEW,
],
SystemFontType::Title | SystemFontType::TitleBold => vec![
windows_fonts::SEGOE_UI_VARIABLE_DISPLAY,
windows_fonts::SEGOE_UI,
],
SystemFontType::Menu => vec![
windows_fonts::SEGOE_UI,
windows_fonts::TAHOMA,
],
SystemFontType::Small => vec![
windows_fonts::SEGOE_UI,
],
SystemFontType::Serif | SystemFontType::SerifBold => vec![
"Cambria",
"Georgia",
"Times New Roman",
],
}
}
fn linux_fallback_chain(&self) -> Vec<&'static str> {
match self {
SystemFontType::Ui | SystemFontType::UiBold => vec![
linux_fonts::CANTARELL,
linux_fonts::UBUNTU,
linux_fonts::NOTO_SANS,
linux_fonts::DEJAVU_SANS,
linux_fonts::LIBERATION_SANS,
linux_fonts::SANS_SERIF,
],
SystemFontType::Monospace | SystemFontType::MonospaceBold | SystemFontType::MonospaceItalic => vec![
linux_fonts::UBUNTU_MONO,
linux_fonts::HACK,
linux_fonts::NOTO_MONO,
linux_fonts::DEJAVU_SANS_MONO,
linux_fonts::LIBERATION_MONO,
linux_fonts::MONOSPACE,
],
SystemFontType::Title | SystemFontType::TitleBold => vec![
linux_fonts::CANTARELL,
linux_fonts::UBUNTU,
linux_fonts::NOTO_SANS,
],
SystemFontType::Menu => vec![
linux_fonts::CANTARELL,
linux_fonts::UBUNTU,
linux_fonts::NOTO_SANS,
],
SystemFontType::Small => vec![
linux_fonts::CANTARELL,
linux_fonts::UBUNTU,
linux_fonts::NOTO_SANS,
],
SystemFontType::Serif | SystemFontType::SerifBold => vec![
linux_fonts::NOTO_SERIF,
linux_fonts::DEJAVU_SERIF,
linux_fonts::LIBERATION_SERIF,
linux_fonts::SERIF,
],
}
}
fn android_fallback_chain(&self) -> Vec<&'static str> {
match self {
SystemFontType::Ui | SystemFontType::UiBold => vec!["Roboto", "Noto Sans"],
SystemFontType::Monospace | SystemFontType::MonospaceBold | SystemFontType::MonospaceItalic => {
vec!["Roboto Mono", "Droid Sans Mono", "monospace"]
}
SystemFontType::Title | SystemFontType::TitleBold => vec!["Roboto", "Noto Sans"],
SystemFontType::Menu => vec!["Roboto"],
SystemFontType::Small => vec!["Roboto"],
SystemFontType::Serif | SystemFontType::SerifBold => vec!["Noto Serif", "Droid Serif", "serif"],
}
}
fn generic_fallback_chain(&self) -> Vec<&'static str> {
match self {
SystemFontType::Ui | SystemFontType::UiBold => vec!["sans-serif"],
SystemFontType::Monospace | SystemFontType::MonospaceBold | SystemFontType::MonospaceItalic => {
vec!["monospace"]
}
SystemFontType::Title | SystemFontType::TitleBold => vec!["sans-serif"],
SystemFontType::Menu => vec!["sans-serif"],
SystemFontType::Small => vec!["sans-serif"],
SystemFontType::Serif | SystemFontType::SerifBold => vec!["serif"],
}
}
}
impl SystemStyle {
pub fn to_json_string(&self) -> AzString {
use alloc::format;
fn opt_color(c: &OptionColorU) -> alloc::string::String {
match c.as_ref() {
Some(c) => format!("\"#{:02x}{:02x}{:02x}{:02x}\"", c.r, c.g, c.b, c.a),
None => "null".into(),
}
}
fn opt_str(s: &OptionString) -> alloc::string::String {
match s.as_ref() {
Some(s) => format!("\"{}\"", s.as_str()),
None => "null".into(),
}
}
fn opt_f32(v: &OptionF32) -> alloc::string::String {
match v.into_option() {
Some(v) => format!("{:.2}", v),
None => "null".into(),
}
}
fn opt_u16(v: &OptionU16) -> alloc::string::String {
match v.into_option() {
Some(v) => format!("{}", v),
None => "null".into(),
}
}
fn opt_px(v: &OptionPixelValue) -> alloc::string::String {
match v.as_ref() {
Some(v) => format!("{:.1}", v.to_pixels_internal(0.0, 0.0, 0.0)),
None => "null".into(),
}
}
let tm = &self.metrics.titlebar;
let inp = &self.input;
let tr = &self.text_rendering;
let acc = &self.accessibility;
let sp = &self.scrollbar_preferences;
let lnx = &self.linux;
let vh = &self.visual_hints;
let anim = &self.animation;
let audio = &self.audio;
let json = format!(
r#"{{
"theme": "{:?}",
"platform": "{:?}",
"os_version": "{:?}:{}",
"language": "{}",
"prefers_reduced_motion": {:?},
"prefers_high_contrast": {:?},
"colors": {{
"text": {},
"secondary_text": {},
"tertiary_text": {},
"background": {},
"accent": {},
"accent_text": {},
"button_face": {},
"button_text": {},
"disabled_text": {},
"window_background": {},
"under_page_background": {},
"selection_background": {},
"selection_text": {},
"selection_background_inactive": {},
"selection_text_inactive": {},
"link": {},
"separator": {},
"grid": {},
"find_highlight": {},
"sidebar_background": {},
"sidebar_selection": {}
}},
"fonts": {{
"ui_font": {},
"ui_font_size": {},
"monospace_font": {},
"title_font": {},
"menu_font": {},
"small_font": {}
}},
"titlebar": {{
"button_side": "{:?}",
"height": {},
"button_area_width": {},
"padding_horizontal": {},
"title_font": {},
"title_font_size": {},
"title_font_weight": {},
"has_close": {},
"has_minimize": {},
"has_maximize": {},
"has_fullscreen": {}
}},
"input": {{
"double_click_time_ms": {},
"double_click_distance_px": {:.1},
"drag_threshold_px": {:.1},
"caret_blink_rate_ms": {},
"caret_width_px": {:.1},
"wheel_scroll_lines": {},
"hover_time_ms": {}
}},
"text_rendering": {{
"font_smoothing_enabled": {},
"subpixel_type": "{:?}",
"font_smoothing_gamma": {},
"increased_contrast": {}
}},
"accessibility": {{
"prefers_bold_text": {},
"prefers_larger_text": {},
"text_scale_factor": {:.2},
"prefers_high_contrast": {},
"prefers_reduced_motion": {},
"prefers_reduced_transparency": {},
"screen_reader_active": {},
"differentiate_without_color": {}
}},
"scrollbar_preferences": {{
"visibility": "{:?}",
"track_click": "{:?}"
}},
"linux": {{
"gtk_theme": {},
"icon_theme": {},
"cursor_theme": {},
"cursor_size": {},
"titlebar_button_layout": {}
}},
"visual_hints": {{
"show_button_images": {},
"show_menu_images": {},
"toolbar_style": "{:?}",
"show_tooltips": {}
}},
"animation": {{
"animations_enabled": {},
"animation_duration_factor": {:.2},
"focus_indicator_behavior": "{:?}"
}},
"audio": {{
"event_sounds_enabled": {},
"input_feedback_sounds_enabled": {}
}}
}}"#,
self.theme,
self.platform,
self.os_version.os, self.os_version.version_id,
self.language.as_str(),
self.prefers_reduced_motion,
self.prefers_high_contrast,
opt_color(&self.colors.text),
opt_color(&self.colors.secondary_text),
opt_color(&self.colors.tertiary_text),
opt_color(&self.colors.background),
opt_color(&self.colors.accent),
opt_color(&self.colors.accent_text),
opt_color(&self.colors.button_face),
opt_color(&self.colors.button_text),
opt_color(&self.colors.disabled_text),
opt_color(&self.colors.window_background),
opt_color(&self.colors.under_page_background),
opt_color(&self.colors.selection_background),
opt_color(&self.colors.selection_text),
opt_color(&self.colors.selection_background_inactive),
opt_color(&self.colors.selection_text_inactive),
opt_color(&self.colors.link),
opt_color(&self.colors.separator),
opt_color(&self.colors.grid),
opt_color(&self.colors.find_highlight),
opt_color(&self.colors.sidebar_background),
opt_color(&self.colors.sidebar_selection),
opt_str(&self.fonts.ui_font),
opt_f32(&self.fonts.ui_font_size),
opt_str(&self.fonts.monospace_font),
opt_str(&self.fonts.title_font),
opt_str(&self.fonts.menu_font),
opt_str(&self.fonts.small_font),
tm.button_side,
opt_px(&tm.height),
opt_px(&tm.button_area_width),
opt_px(&tm.padding_horizontal),
opt_str(&tm.title_font),
opt_f32(&tm.title_font_size),
opt_u16(&tm.title_font_weight),
tm.buttons.has_close,
tm.buttons.has_minimize,
tm.buttons.has_maximize,
tm.buttons.has_fullscreen,
inp.double_click_time_ms,
inp.double_click_distance_px,
inp.drag_threshold_px,
inp.caret_blink_rate_ms,
inp.caret_width_px,
inp.wheel_scroll_lines,
inp.hover_time_ms,
tr.font_smoothing_enabled,
tr.subpixel_type,
tr.font_smoothing_gamma,
tr.increased_contrast,
acc.prefers_bold_text,
acc.prefers_larger_text,
acc.text_scale_factor,
acc.prefers_high_contrast,
acc.prefers_reduced_motion,
acc.prefers_reduced_transparency,
acc.screen_reader_active,
acc.differentiate_without_color,
sp.visibility,
sp.track_click,
opt_str(&lnx.gtk_theme),
opt_str(&lnx.icon_theme),
opt_str(&lnx.cursor_theme),
lnx.cursor_size,
opt_str(&lnx.titlebar_button_layout),
vh.show_button_images,
vh.show_menu_images,
vh.toolbar_style,
vh.show_tooltips,
anim.animations_enabled,
anim.animation_duration_factor,
anim.focus_indicator_behavior,
audio.event_sounds_enabled,
audio.input_feedback_sounds_enabled,
);
AzString::from(json)
}
pub fn detect() -> Self {
Self::default_for_platform()
}
pub fn default_for_platform() -> Self {
#[cfg(target_os = "windows")]
{ defaults::windows_11_light() }
#[cfg(target_os = "macos")]
{ defaults::macos_modern_light() }
#[cfg(target_os = "linux")]
{ defaults::gnome_adwaita_light() }
#[cfg(target_os = "android")]
{ defaults::android_material_light() }
#[cfg(target_os = "ios")]
{ defaults::ios_light() }
#[cfg(not(any(
target_os = "linux",
target_os = "windows",
target_os = "macos",
target_os = "android",
target_os = "ios"
)))]
{ Self::default() }
}
#[inline(always)]
pub fn new() -> Self {
Self::detect()
}
pub fn create_csd_stylesheet(&self) -> Css {
use alloc::format;
use crate::parser2::new_from_str;
let mut css = String::new();
let bg_color = self
.colors
.window_background
.as_option()
.copied()
.unwrap_or(ColorU::new_rgb(240, 240, 240));
let text_color = self
.colors
.text
.as_option()
.copied()
.unwrap_or(ColorU::new_rgb(0, 0, 0));
let accent_color = self
.colors
.accent
.as_option()
.copied()
.unwrap_or(ColorU::new_rgb(0, 120, 215));
let border_color = match self.theme {
Theme::Dark => ColorU::new_rgb(60, 60, 60),
Theme::Light => ColorU::new_rgb(200, 200, 200),
};
let corner_radius = self
.metrics
.corner_radius
.map(|px| {
use crate::props::basic::pixel::DEFAULT_FONT_SIZE;
format!("{}px", px.to_pixels_internal(1.0, DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE))
})
.unwrap_or_else(|| "4px".to_string());
css.push_str(&format!(
".csd-titlebar {{ width: 100%; height: 32px; background: rgb({}, {}, {}); \
border-bottom: 1px solid rgb({}, {}, {}); display: flex; flex-direction: row; \
align-items: center; justify-content: space-between; padding: 0 8px; \
cursor: grab; user-select: none; }} ",
bg_color.r, bg_color.g, bg_color.b, border_color.r, border_color.g, border_color.b,
));
css.push_str(&format!(
".csd-title {{ color: rgb({}, {}, {}); font-size: 13px; flex-grow: 1; text-align: \
center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; \
user-select: none; }} ",
text_color.r, text_color.g, text_color.b,
));
css.push_str(".csd-buttons { display: flex; flex-direction: row; gap: 4px; } ");
css.push_str(&format!(
".csd-button {{ width: 32px; height: 24px; border-radius: {}; background: \
transparent; color: rgb({}, {}, {}); font-size: 16px; line-height: 24px; text-align: \
center; cursor: pointer; user-select: none; }} ",
corner_radius, text_color.r, text_color.g, text_color.b,
));
let hover_color = match self.theme {
Theme::Dark => ColorU::new_rgb(60, 60, 60),
Theme::Light => ColorU::new_rgb(220, 220, 220),
};
css.push_str(&format!(
".csd-button:hover {{ background: rgb({}, {}, {}); }} ",
hover_color.r, hover_color.g, hover_color.b,
));
css.push_str(
".csd-close:hover { background: rgb(232, 17, 35); color: rgb(255, 255, 255); } ",
);
match self.platform {
Platform::MacOs => {
css.push_str(".csd-buttons { position: absolute; left: 8px; } ");
css.push_str(
".csd-close { background: rgb(255, 95, 86); width: 12px; height: 12px; \
border-radius: 50%; } ",
);
css.push_str(
".csd-minimize { background: rgb(255, 189, 46); width: 12px; height: 12px; \
border-radius: 50%; } ",
);
css.push_str(
".csd-maximize { background: rgb(40, 201, 64); width: 12px; height: 12px; \
border-radius: 50%; } ",
);
}
Platform::Linux(_) => {
css.push_str(".csd-title { text-align: left; } ");
}
_ => {
}
}
let (mut parsed_css, _warnings) = new_from_str(&css);
for rule in parsed_css.rules.as_mut() {
rule.priority = crate::css::rule_priority::SYSTEM;
}
parsed_css
}
}
pub fn detect_linux_desktop_env() -> DesktopEnvironment {
if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") {
let desktop_lower = desktop.to_lowercase();
if desktop_lower.contains("gnome") {
return DesktopEnvironment::Gnome;
}
if desktop_lower.contains("kde") || desktop_lower.contains("plasma") {
return DesktopEnvironment::Kde;
}
if desktop_lower.contains("xfce") {
return DesktopEnvironment::Other(AzString::from_const_str("XFCE"));
}
if desktop_lower.contains("unity") {
return DesktopEnvironment::Other(AzString::from_const_str("Unity"));
}
if desktop_lower.contains("cinnamon") {
return DesktopEnvironment::Other(AzString::from_const_str("Cinnamon"));
}
if desktop_lower.contains("mate") {
return DesktopEnvironment::Other(AzString::from_const_str("MATE"));
}
if desktop_lower.contains("lxde") || desktop_lower.contains("lxqt") {
return DesktopEnvironment::Other(AzString::from(desktop.to_uppercase()));
}
if desktop_lower.contains("budgie") {
return DesktopEnvironment::Other(AzString::from_const_str("Budgie"));
}
if desktop_lower.contains("pantheon") {
return DesktopEnvironment::Other(AzString::from_const_str("Pantheon"));
}
if desktop_lower.contains("deepin") {
return DesktopEnvironment::Other(AzString::from_const_str("Deepin"));
}
if desktop_lower.contains("hyprland") {
return DesktopEnvironment::Other(AzString::from_const_str("Hyprland"));
}
if desktop_lower.contains("sway") {
return DesktopEnvironment::Other(AzString::from_const_str("Sway"));
}
if desktop_lower.contains("i3") {
return DesktopEnvironment::Other(AzString::from_const_str("i3"));
}
return DesktopEnvironment::Other(AzString::from(desktop));
}
if let Ok(session) = std::env::var("DESKTOP_SESSION") {
let session_lower = session.to_lowercase();
if session_lower.contains("gnome") {
return DesktopEnvironment::Gnome;
}
if session_lower.contains("plasma") || session_lower.contains("kde") {
return DesktopEnvironment::Kde;
}
if session_lower.contains("xfce") {
return DesktopEnvironment::Other(AzString::from_const_str("XFCE"));
}
if session_lower.contains("cinnamon") {
return DesktopEnvironment::Other(AzString::from_const_str("Cinnamon"));
}
return DesktopEnvironment::Other(AzString::from(session));
}
if std::env::var("GNOME_DESKTOP_SESSION_ID").is_ok() {
return DesktopEnvironment::Gnome;
}
if std::env::var("KDE_FULL_SESSION").is_ok() {
return DesktopEnvironment::Kde;
}
if std::env::var("HYPRLAND_INSTANCE_SIGNATURE").is_ok() {
return DesktopEnvironment::Other(AzString::from_const_str("Hyprland"));
}
if std::env::var("SWAYSOCK").is_ok() {
return DesktopEnvironment::Other(AzString::from_const_str("Sway"));
}
if std::env::var("I3SOCK").is_ok() {
return DesktopEnvironment::Other(AzString::from_const_str("i3"));
}
DesktopEnvironment::Other(AzString::from_const_str("Unknown"))
}
pub fn detect_system_language() -> AzString {
let env_vars = ["LANGUAGE", "LC_ALL", "LC_MESSAGES", "LANG"];
for var in &env_vars {
if let Ok(value) = std::env::var(var) {
let value = value.trim();
if value.is_empty() || value == "C" || value == "POSIX" {
continue;
}
let lang = value
.split('.') .next()
.unwrap_or(value)
.split(':') .next()
.unwrap_or(value);
if !lang.is_empty() {
return AzString::from(lang.replace('_', "-"));
}
}
}
AzString::from_const_str("en-US")
}
pub mod defaults {
use crate::{
corety::{AzString, OptionF32, OptionString},
dynamic_selector::{BoolCondition, OsVersion},
props::{
basic::{
color::{ColorU, OptionColorU},
pixel::{PixelValue, OptionPixelValue},
},
layout::{
dimensions::LayoutWidth,
spacing::{LayoutPaddingLeft, LayoutPaddingRight},
},
style::{
background::StyleBackgroundContent,
scrollbar::{
ComputedScrollbarStyle, OverflowScrolling, OverscrollBehavior, ScrollBehavior,
ScrollPhysics, ScrollbarInfo,
SCROLLBAR_ANDROID_DARK, SCROLLBAR_ANDROID_LIGHT, SCROLLBAR_CLASSIC_DARK,
SCROLLBAR_CLASSIC_LIGHT, SCROLLBAR_IOS_DARK, SCROLLBAR_IOS_LIGHT,
SCROLLBAR_MACOS_DARK, SCROLLBAR_MACOS_LIGHT, SCROLLBAR_WINDOWS_DARK,
SCROLLBAR_WINDOWS_LIGHT,
},
},
},
system::{
DesktopEnvironment, Platform, SystemColors, SystemFonts, SystemMetrics, SystemStyle,
Theme, IconStyleOptions, TitlebarMetrics,
},
};
pub const SCROLLBAR_WINDOWS_CLASSIC: ScrollbarInfo = ScrollbarInfo {
width: LayoutWidth::Px(crate::props::basic::pixel::PixelValue::const_px(17)),
padding_left: LayoutPaddingLeft {
inner: crate::props::basic::pixel::PixelValue::const_px(0),
},
padding_right: LayoutPaddingRight {
inner: crate::props::basic::pixel::PixelValue::const_px(0),
},
track: StyleBackgroundContent::Color(ColorU {
r: 223,
g: 223,
b: 223,
a: 255,
}), thumb: StyleBackgroundContent::Color(ColorU {
r: 208,
g: 208,
b: 208,
a: 255,
}), button: StyleBackgroundContent::Color(ColorU {
r: 208,
g: 208,
b: 208,
a: 255,
}),
corner: StyleBackgroundContent::Color(ColorU {
r: 223,
g: 223,
b: 223,
a: 255,
}),
resizer: StyleBackgroundContent::Color(ColorU::TRANSPARENT),
clip_to_container_border: false,
scroll_behavior: ScrollBehavior::Auto,
overscroll_behavior_x: OverscrollBehavior::None,
overscroll_behavior_y: OverscrollBehavior::None,
overflow_scrolling: OverflowScrolling::Auto,
};
pub const SCROLLBAR_MACOS_AQUA: ScrollbarInfo = ScrollbarInfo {
width: LayoutWidth::Px(crate::props::basic::pixel::PixelValue::const_px(15)),
padding_left: LayoutPaddingLeft {
inner: crate::props::basic::pixel::PixelValue::const_px(0),
},
padding_right: LayoutPaddingRight {
inner: crate::props::basic::pixel::PixelValue::const_px(0),
},
track: StyleBackgroundContent::Color(ColorU {
r: 238,
g: 238,
b: 238,
a: 128,
}), thumb: StyleBackgroundContent::Color(ColorU {
r: 105,
g: 173,
b: 255,
a: 255,
}), button: StyleBackgroundContent::Color(ColorU {
r: 105,
g: 173,
b: 255,
a: 255,
}),
corner: StyleBackgroundContent::Color(ColorU::TRANSPARENT),
resizer: StyleBackgroundContent::Color(ColorU::TRANSPARENT),
clip_to_container_border: true,
scroll_behavior: ScrollBehavior::Smooth,
overscroll_behavior_x: OverscrollBehavior::Auto,
overscroll_behavior_y: OverscrollBehavior::Auto,
overflow_scrolling: OverflowScrolling::Auto,
};
pub const SCROLLBAR_KDE_OXYGEN: ScrollbarInfo = ScrollbarInfo {
width: LayoutWidth::Px(crate::props::basic::pixel::PixelValue::const_px(14)),
padding_left: LayoutPaddingLeft {
inner: crate::props::basic::pixel::PixelValue::const_px(2),
},
padding_right: LayoutPaddingRight {
inner: crate::props::basic::pixel::PixelValue::const_px(2),
},
track: StyleBackgroundContent::Color(ColorU {
r: 242,
g: 242,
b: 242,
a: 255,
}),
thumb: StyleBackgroundContent::Color(ColorU {
r: 177,
g: 177,
b: 177,
a: 255,
}),
button: StyleBackgroundContent::Color(ColorU {
r: 216,
g: 216,
b: 216,
a: 255,
}),
corner: StyleBackgroundContent::Color(ColorU::TRANSPARENT),
resizer: StyleBackgroundContent::Color(ColorU::TRANSPARENT),
clip_to_container_border: false,
scroll_behavior: ScrollBehavior::Auto,
overscroll_behavior_x: OverscrollBehavior::Auto,
overscroll_behavior_y: OverscrollBehavior::Auto,
overflow_scrolling: OverflowScrolling::Auto,
};
fn scrollbar_info_to_computed(info: &ScrollbarInfo) -> ComputedScrollbarStyle {
ComputedScrollbarStyle {
width: Some(info.width.clone()),
thumb_color: match info.thumb {
StyleBackgroundContent::Color(c) => Some(c),
_ => None,
},
track_color: match info.track {
StyleBackgroundContent::Color(c) => Some(c),
_ => None,
},
}
}
pub fn windows_11_light() -> SystemStyle {
SystemStyle {
theme: Theme::Light,
platform: Platform::Windows,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
background: OptionColorU::Some(ColorU::new_rgb(243, 243, 243)),
accent: OptionColorU::Some(ColorU::new_rgb(0, 95, 184)),
window_background: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
selection_background: OptionColorU::Some(ColorU::new_rgb(0, 120, 215)),
selection_text: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Segoe UI Variable Text".into()),
ui_font_size: OptionF32::Some(9.0),
monospace_font: OptionString::Some("Consolas".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(4.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(12.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(6.0)),
titlebar: TitlebarMetrics::windows(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_WINDOWS_LIGHT))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::WIN_11,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::windows(),
..Default::default()
}
}
pub fn windows_11_dark() -> SystemStyle {
SystemStyle {
theme: Theme::Dark,
platform: Platform::Windows,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
background: OptionColorU::Some(ColorU::new_rgb(32, 32, 32)),
accent: OptionColorU::Some(ColorU::new_rgb(0, 120, 215)),
window_background: OptionColorU::Some(ColorU::new_rgb(25, 25, 25)),
selection_background: OptionColorU::Some(ColorU::new_rgb(0, 120, 215)),
selection_text: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Segoe UI Variable Text".into()),
ui_font_size: OptionF32::Some(9.0),
monospace_font: OptionString::Some("Consolas".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(4.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(12.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(6.0)),
titlebar: TitlebarMetrics::windows(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_WINDOWS_DARK))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::WIN_11,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::windows(),
..Default::default()
}
}
pub fn windows_7_aero() -> SystemStyle {
SystemStyle {
theme: Theme::Light,
platform: Platform::Windows,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
background: OptionColorU::Some(ColorU::new_rgb(240, 240, 240)),
accent: OptionColorU::Some(ColorU::new_rgb(51, 153, 255)),
window_background: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
selection_background: OptionColorU::Some(ColorU::new_rgb(51, 153, 255)),
selection_text: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Segoe UI".into()),
ui_font_size: OptionF32::Some(9.0),
monospace_font: OptionString::Some("Consolas".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(6.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(10.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(5.0)),
titlebar: TitlebarMetrics::windows(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_CLASSIC_LIGHT))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::WIN_7,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::windows(),
..Default::default()
}
}
pub fn windows_xp_luna() -> SystemStyle {
SystemStyle {
theme: Theme::Light,
platform: Platform::Windows,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
background: OptionColorU::Some(ColorU::new_rgb(236, 233, 216)),
accent: OptionColorU::Some(ColorU::new_rgb(49, 106, 197)),
window_background: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
selection_background: OptionColorU::Some(ColorU::new_rgb(49, 106, 197)),
selection_text: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Tahoma".into()),
ui_font_size: OptionF32::Some(8.0),
monospace_font: OptionString::Some("Lucida Console".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(3.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(8.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(4.0)),
titlebar: TitlebarMetrics::windows(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_WINDOWS_CLASSIC))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::WIN_XP,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::windows(),
..Default::default()
}
}
pub fn macos_modern_light() -> SystemStyle {
SystemStyle {
platform: Platform::MacOs,
theme: Theme::Light,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new(0, 0, 0, 221)),
background: OptionColorU::Some(ColorU::new_rgb(242, 242, 247)),
accent: OptionColorU::Some(ColorU::new_rgb(0, 122, 255)),
window_background: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
selection_background: OptionColorU::Some(ColorU::new(0, 122, 255, 128)),
selection_text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some(".SF NS".into()),
ui_font_size: OptionF32::Some(13.0),
monospace_font: OptionString::Some("Menlo".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(8.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(16.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(6.0)),
titlebar: TitlebarMetrics::macos(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_MACOS_LIGHT))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::MACOS_SONOMA,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::macos(),
..Default::default()
}
}
pub fn macos_modern_dark() -> SystemStyle {
SystemStyle {
platform: Platform::MacOs,
theme: Theme::Dark,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new(255, 255, 255, 221)),
background: OptionColorU::Some(ColorU::new_rgb(28, 28, 30)),
accent: OptionColorU::Some(ColorU::new_rgb(10, 132, 255)),
window_background: OptionColorU::Some(ColorU::new_rgb(44, 44, 46)),
selection_background: OptionColorU::Some(ColorU::new(10, 132, 255, 128)),
selection_text: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some(".SF NS".into()),
ui_font_size: OptionF32::Some(13.0),
monospace_font: OptionString::Some("SF Mono".into()),
monospace_font_size: OptionF32::Some(12.0),
title_font: OptionString::Some(".SF NS".into()),
title_font_size: OptionF32::Some(13.0),
menu_font: OptionString::Some(".SF NS".into()),
menu_font_size: OptionF32::Some(13.0),
small_font: OptionString::Some(".SF NS".into()),
small_font_size: OptionF32::Some(11.0),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(8.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(16.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(6.0)),
titlebar: TitlebarMetrics::macos(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_MACOS_DARK))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::MACOS_SONOMA,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::macos(),
..Default::default()
}
}
pub fn macos_aqua() -> SystemStyle {
SystemStyle {
platform: Platform::MacOs,
theme: Theme::Light,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
background: OptionColorU::Some(ColorU::new_rgb(229, 229, 229)),
accent: OptionColorU::Some(ColorU::new_rgb(63, 128, 234)),
window_background: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Lucida Grande".into()),
ui_font_size: OptionF32::Some(13.0),
monospace_font: OptionString::Some("Monaco".into()),
monospace_font_size: OptionF32::Some(12.0),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(12.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(16.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(6.0)),
titlebar: TitlebarMetrics::macos(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_MACOS_AQUA))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::MACOS_TIGER,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::macos(),
..Default::default()
}
}
pub fn gnome_adwaita_light() -> SystemStyle {
SystemStyle {
platform: Platform::Linux(DesktopEnvironment::Gnome),
theme: Theme::Light,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(46, 52, 54)),
background: OptionColorU::Some(ColorU::new_rgb(249, 249, 249)),
accent: OptionColorU::Some(ColorU::new_rgb(53, 132, 228)),
window_background: OptionColorU::Some(ColorU::new_rgb(237, 237, 237)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Cantarell".into()),
ui_font_size: OptionF32::Some(11.0),
monospace_font: OptionString::Some("Monospace".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(4.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(12.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(8.0)),
titlebar: TitlebarMetrics::linux_gnome(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_CLASSIC_LIGHT))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::LINUX_6_0,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
..Default::default()
}
}
pub fn gnome_adwaita_dark() -> SystemStyle {
SystemStyle {
platform: Platform::Linux(DesktopEnvironment::Gnome),
theme: Theme::Dark,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(238, 238, 236)),
background: OptionColorU::Some(ColorU::new_rgb(36, 36, 36)),
accent: OptionColorU::Some(ColorU::new_rgb(53, 132, 228)),
window_background: OptionColorU::Some(ColorU::new_rgb(48, 48, 48)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Cantarell".into()),
ui_font_size: OptionF32::Some(11.0),
monospace_font: OptionString::Some("Monospace".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(4.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(12.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(8.0)),
titlebar: TitlebarMetrics::linux_gnome(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_CLASSIC_DARK))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::LINUX_6_0,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
..Default::default()
}
}
pub fn gtk2_clearlooks() -> SystemStyle {
SystemStyle {
platform: Platform::Linux(DesktopEnvironment::Gnome),
theme: Theme::Light,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
background: OptionColorU::Some(ColorU::new_rgb(239, 239, 239)),
accent: OptionColorU::Some(ColorU::new_rgb(245, 121, 0)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("DejaVu Sans".into()),
ui_font_size: OptionF32::Some(10.0),
monospace_font: OptionString::Some("DejaVu Sans Mono".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(4.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(10.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(6.0)),
titlebar: TitlebarMetrics::linux_gnome(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_CLASSIC_LIGHT))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::LINUX_2_6,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
..Default::default()
}
}
pub fn kde_breeze_light() -> SystemStyle {
SystemStyle {
platform: Platform::Linux(DesktopEnvironment::Kde),
theme: Theme::Light,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(31, 36, 39)),
background: OptionColorU::Some(ColorU::new_rgb(239, 240, 241)),
accent: OptionColorU::Some(ColorU::new_rgb(61, 174, 233)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Noto Sans".into()),
ui_font_size: OptionF32::Some(10.0),
monospace_font: OptionString::Some("Hack".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(4.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(12.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(6.0)),
titlebar: TitlebarMetrics::linux_gnome(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_KDE_OXYGEN))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::LINUX_6_0,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
..Default::default()
}
}
pub fn android_material_light() -> SystemStyle {
SystemStyle {
platform: Platform::Android,
theme: Theme::Light,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
background: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
accent: OptionColorU::Some(ColorU::new_rgb(98, 0, 238)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Roboto".into()),
ui_font_size: OptionF32::Some(14.0),
monospace_font: OptionString::Some("Droid Sans Mono".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(12.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(16.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(10.0)),
titlebar: TitlebarMetrics::android(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_ANDROID_LIGHT))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::ANDROID_14,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::android(),
..Default::default()
}
}
pub fn android_holo_dark() -> SystemStyle {
SystemStyle {
platform: Platform::Android,
theme: Theme::Dark,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(255, 255, 255)),
background: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
accent: OptionColorU::Some(ColorU::new_rgb(51, 181, 229)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some("Roboto".into()),
ui_font_size: OptionF32::Some(14.0),
monospace_font: OptionString::Some("Droid Sans Mono".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(2.0)),
border_width: OptionPixelValue::Some(PixelValue::px(1.0)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(12.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(8.0)),
titlebar: TitlebarMetrics::android(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_ANDROID_DARK))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::ANDROID_ICE_CREAM_SANDWICH,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::android(),
..Default::default()
}
}
pub fn ios_light() -> SystemStyle {
SystemStyle {
platform: Platform::Ios,
theme: Theme::Light,
colors: SystemColors {
text: OptionColorU::Some(ColorU::new_rgb(0, 0, 0)),
background: OptionColorU::Some(ColorU::new_rgb(242, 242, 247)),
accent: OptionColorU::Some(ColorU::new_rgb(0, 122, 255)),
..Default::default()
},
fonts: SystemFonts {
ui_font: OptionString::Some(".SFUI-Display-Regular".into()),
ui_font_size: OptionF32::Some(17.0),
monospace_font: OptionString::Some("Menlo".into()),
..Default::default()
},
metrics: SystemMetrics {
corner_radius: OptionPixelValue::Some(PixelValue::px(10.0)),
border_width: OptionPixelValue::Some(PixelValue::px(0.5)),
button_padding_horizontal: OptionPixelValue::Some(PixelValue::px(20.0)),
button_padding_vertical: OptionPixelValue::Some(PixelValue::px(12.0)),
titlebar: TitlebarMetrics::ios(),
},
scrollbar: Some(Box::new(scrollbar_info_to_computed(&SCROLLBAR_IOS_LIGHT))),
app_specific_stylesheet: None,
icon_style: IconStyleOptions::default(),
language: AzString::from_const_str("en-US"),
os_version: OsVersion::IOS_17,
prefers_reduced_motion: BoolCondition::False,
prefers_high_contrast: BoolCondition::False,
scroll_physics: ScrollPhysics::ios(),
..Default::default()
}
}
}