1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
//! System config types.

use std::{fmt, time::Duration};

use serde::{Deserialize, Serialize};

use zng_txt::Txt;
use zng_unit::{Dip, DipSize, Rgba};

/// System settings needed for implementing double/triple clicks.
#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Deserialize)]
pub struct MultiClickConfig {
    /// Maximum time interval between clicks.
    ///
    /// Only repeated clicks within this time interval can count as double-clicks.
    pub time: Duration,

    /// Maximum (x, y) distance in pixels.
    ///
    /// Only repeated clicks that are within this distance of the first click can count as double-clicks.
    pub area: DipSize,
}
impl Default for MultiClickConfig {
    /// `500ms` and `4, 4`.
    fn default() -> Self {
        Self {
            time: Duration::from_millis(500),
            area: DipSize::splat(Dip::new(4)),
        }
    }
}

/// System settings needed to implementing touch gestures.
#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Deserialize)]
pub struct TouchConfig {
    /// Maximum (x, y) distance between a touch start and end that generates a touch click.
    ///
    /// Area can be disregarded if the touch is not ambiguous. This usually defines the initial lag
    /// for a single finger drag gesture.
    pub tap_area: DipSize,

    /// Maximum (x, y) distance that a subsequent touch click is linked with the previous one as a double click.
    ///
    /// Area can be disregarded if the touch is not ambiguous.
    pub double_tap_area: DipSize,

    /// Maximum time between start and end in the `tap_area` that generates a touch click.
    ///
    /// Time can be disregarded if the touch is not ambiguous. This usually defines the *long press* delay.
    pub tap_max_time: Duration,

    /// Maximum time between taps that generates a double click.
    pub double_tap_max_time: Duration,

    /// Minimum velocity that can be considered a fling gesture, in dip per seconds.
    pub min_fling_velocity: Dip,

    /// Fling velocity ceiling, in dip per seconds.
    pub max_fling_velocity: Dip,
}
impl Default for TouchConfig {
    fn default() -> Self {
        Self {
            tap_area: DipSize::splat(Dip::new(8)),
            double_tap_area: DipSize::splat(Dip::new(28)),
            tap_max_time: Duration::from_millis(500),
            double_tap_max_time: Duration::from_millis(500),
            min_fling_velocity: Dip::new(50),
            max_fling_velocity: Dip::new(8000),
        }
    }
}

/// System settings that define the key pressed repeat.
#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Deserialize)]
pub struct KeyRepeatConfig {
    /// Delay before repeat starts.
    pub start_delay: Duration,
    /// Delay before each repeat event after the first.
    pub interval: Duration,
}
impl Default for KeyRepeatConfig {
    /// 600ms, 100ms.
    fn default() -> Self {
        Self {
            start_delay: Duration::from_millis(600),
            interval: Duration::from_millis(100),
        }
    }
}

/// System settings that control animations.
#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, Deserialize)]
pub struct AnimationsConfig {
    /// If animation are enabled.
    ///
    /// People with photo-sensitive epilepsy usually disable animations system wide.
    pub enabled: bool,

    /// Interval of the caret blink animation.
    ///
    /// This is the duration the cursor stays visible.
    pub caret_blink_interval: Duration,
    /// Duration after which the blink animation stops.
    pub caret_blink_timeout: Duration,
}
impl Default for AnimationsConfig {
    /// true, 530ms, 5s.
    fn default() -> Self {
        Self {
            enabled: true,
            caret_blink_interval: Duration::from_millis(530),
            caret_blink_timeout: Duration::from_secs(5),
        }
    }
}

/// System settings that define the locale.
#[derive(Debug, Clone, Serialize, PartialEq, Eq, Deserialize, Default)]
pub struct LocaleConfig {
    /// BCP-47 language tags, if the locale can be obtained.
    pub langs: Vec<Txt>,
}

/// Text anti-aliasing.
#[derive(Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum FontAntiAliasing {
    /// Uses the operating system configuration.
    #[default]
    Default,
    /// Sub-pixel anti-aliasing if a fast implementation is available, otherwise uses `Alpha`.
    Subpixel,
    /// Alpha blending anti-aliasing.
    Alpha,
    /// Disable anti-aliasing.
    Mono,
}
impl fmt::Debug for FontAntiAliasing {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if f.alternate() {
            write!(f, "FontAntiAliasing::")?;
        }
        match self {
            FontAntiAliasing::Default => write!(f, "Default"),
            FontAntiAliasing::Subpixel => write!(f, "Subpixel"),
            FontAntiAliasing::Alpha => write!(f, "Alpha"),
            FontAntiAliasing::Mono => write!(f, "Mono"),
        }
    }
}

/// Color scheme preference.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ColorScheme {
    /// Dark text, light background.
    Light,

    /// Light text, dark background.
    Dark,
}
impl Default for ColorScheme {
    /// Light.
    fn default() -> Self {
        ColorScheme::Light
    }
}

/// System colors and color scheme.
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct ColorsConfig {
    /// Color scheme (light/dark) preference.
    pub scheme: ColorScheme,
    /// Accent color.
    ///
    /// Accent color preference.
    ///
    /// Expect a saturated color that contrasts with the text color.
    pub accent: Rgba,
}
impl Default for ColorsConfig {
    fn default() -> Self {
        Self {
            scheme: Default::default(),
            accent: Rgba::new(10, 10, 200, 255),
        }
    }
}

#[cfg(feature = "var")]
zng_var::impl_from_and_into_var! {
    fn from(some: ColorScheme) -> Option<ColorScheme>;
}

/// Window chrome (decorations) preference.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct ChromeConfig {
    /// Window manager prefers that the window renders a custom chrome.
    ///
    /// This is also called "Client-Side Decorations", it is `true` in GNOME+Wayland.
    pub prefer_custom: bool,

    /// If the Window manager provides a chrome.
    ///
    /// When this is `false` the view-process implementation may provide just a very basic fallback chrome,
    /// if the app-process still requests system chrome.
    pub provided: bool,
}
impl ChromeConfig {
    /// If system prefers custom and does not provide chrome.
    ///
    /// Note that a chromeless window is not forbidden if this is `true`.
    pub fn needs_custom(&self) -> bool {
        self.prefer_custom && !self.provided
    }
}
impl Default for ChromeConfig {
    fn default() -> Self {
        Self {
            prefer_custom: false,
            provided: true,
        }
    }
}