Skip to main content

halley_config/layout/
types.rs

1use halley_core::cluster_layout::ClusterWorkspaceLayoutKind;
2use halley_core::viewport::FocusRing;
3use regex::Regex;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub enum NodeBorderColorMode {
7    UseWindowActive,
8    UseWindowInactive,
9    UseWindowSecondaryActive,
10    UseWindowSecondaryInactive,
11}
12
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum NodeDisplayPolicy {
15    Off,
16    Hover,
17    Always,
18}
19
20#[derive(Clone, Copy, Debug, PartialEq)]
21pub enum NodeBackgroundColorMode {
22    Auto,
23    Theme,
24    Light,
25    Dark,
26    Fixed { r: f32, g: f32, b: f32 },
27}
28
29#[derive(Clone, Copy, Debug, Eq, PartialEq)]
30pub enum ShapeStyle {
31    Square,
32    Squircle,
33}
34
35#[derive(Clone, Copy, Debug, PartialEq)]
36pub enum OverlayColorMode {
37    Auto,
38    Light,
39    Dark,
40    Fixed { r: f32, g: f32, b: f32 },
41}
42
43#[derive(Clone, Copy, Debug, Eq, PartialEq)]
44pub enum OverlayShape {
45    Square,
46    Rounded,
47}
48
49#[derive(Clone, Copy, Debug, Eq, PartialEq)]
50pub enum OverlayBorderSource {
51    Primary,
52    Secondary,
53}
54
55#[derive(Clone, Copy, Debug, PartialEq)]
56pub struct OverlayStyleConfig {
57    pub background_color: OverlayColorMode,
58    pub text_color: OverlayColorMode,
59    pub shape: OverlayShape,
60    pub borders: bool,
61    pub border_source: OverlayBorderSource,
62}
63
64impl Default for OverlayStyleConfig {
65    fn default() -> Self {
66        Self {
67            background_color: OverlayColorMode::Auto,
68            text_color: OverlayColorMode::Auto,
69            shape: OverlayShape::Square,
70            borders: true,
71            border_source: OverlayBorderSource::Primary,
72        }
73    }
74}
75
76#[derive(Clone, Copy, Debug, PartialEq)]
77pub struct AnimationToggleConfig {
78    pub enabled: bool,
79}
80
81impl Default for AnimationToggleConfig {
82    fn default() -> Self {
83        Self { enabled: true }
84    }
85}
86
87#[derive(Clone, Copy, Debug, PartialEq)]
88pub struct TimedAnimationConfig {
89    pub enabled: bool,
90    pub duration_ms: u64,
91}
92
93impl TimedAnimationConfig {
94    pub const fn new(enabled: bool, duration_ms: u64) -> Self {
95        Self {
96            enabled,
97            duration_ms,
98        }
99    }
100}
101
102#[derive(Clone, Copy, Debug, Eq, PartialEq)]
103pub enum WindowCloseAnimationStyle {
104    Shrink,
105}
106
107#[derive(Clone, Copy, Debug, PartialEq)]
108pub struct WindowCloseAnimationConfig {
109    pub enabled: bool,
110    pub duration_ms: u64,
111    pub style: WindowCloseAnimationStyle,
112}
113
114impl WindowCloseAnimationConfig {
115    pub const fn new(enabled: bool, duration_ms: u64, style: WindowCloseAnimationStyle) -> Self {
116        Self {
117            enabled,
118            duration_ms,
119            style,
120        }
121    }
122}
123
124#[derive(Clone, Copy, Debug, PartialEq)]
125pub struct AnimationsConfig {
126    pub enabled: bool,
127    pub smooth_resize: TimedAnimationConfig,
128    pub window_close: WindowCloseAnimationConfig,
129    pub window_open: TimedAnimationConfig,
130    pub tile: TimedAnimationConfig,
131    pub stack: TimedAnimationConfig,
132}
133
134impl Default for AnimationsConfig {
135    fn default() -> Self {
136        Self {
137            enabled: true,
138            smooth_resize: TimedAnimationConfig::new(true, 90),
139            window_close: WindowCloseAnimationConfig::new(
140                true,
141                250,
142                WindowCloseAnimationStyle::Shrink,
143            ),
144            window_open: TimedAnimationConfig::new(true, 620),
145            tile: TimedAnimationConfig::new(true, 240),
146            stack: TimedAnimationConfig::new(true, 220),
147        }
148    }
149}
150
151#[derive(Clone, Debug, PartialEq)]
152pub struct ScreenshotConfig {
153    pub directory: String,
154    pub highlight_color: OverlayColorMode,
155    pub background_color: OverlayColorMode,
156}
157
158impl Default for ScreenshotConfig {
159    fn default() -> Self {
160        let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
161        Self {
162            directory: format!("{home}/Pictures/Screenshots"),
163            highlight_color: OverlayColorMode::Auto,
164            background_color: OverlayColorMode::Auto,
165        }
166    }
167}
168
169#[derive(Clone, Copy, Debug, PartialEq)]
170pub struct DecorationBorderColor {
171    pub r: f32,
172    pub g: f32,
173    pub b: f32,
174}
175
176#[derive(Clone, Copy, Debug, PartialEq)]
177pub struct PrimaryBorderConfig {
178    pub size_px: i32,
179    pub radius_px: i32,
180    pub color_focused: DecorationBorderColor,
181    pub color_unfocused: DecorationBorderColor,
182}
183
184#[derive(Clone, Copy, Debug, PartialEq)]
185pub struct SecondaryBorderConfig {
186    pub enabled: bool,
187    pub size_px: i32,
188    pub gap_px: i32,
189    pub color_focused: DecorationBorderColor,
190    pub color_unfocused: DecorationBorderColor,
191}
192
193#[derive(Clone, Copy, Debug, PartialEq)]
194pub struct DecorationsConfig {
195    pub border: PrimaryBorderConfig,
196    pub secondary_border: SecondaryBorderConfig,
197    pub resize_using_border: bool,
198}
199
200impl Default for PrimaryBorderConfig {
201    fn default() -> Self {
202        Self {
203            size_px: 3,
204            radius_px: 0,
205            color_focused: DecorationBorderColor {
206                r: 0.22,
207                g: 0.82,
208                b: 0.92,
209            },
210            color_unfocused: DecorationBorderColor {
211                r: 0.28,
212                g: 0.30,
213                b: 0.35,
214            },
215        }
216    }
217}
218
219impl Default for SecondaryBorderConfig {
220    fn default() -> Self {
221        Self {
222            enabled: false,
223            size_px: 1,
224            gap_px: 2,
225            color_focused: DecorationBorderColor {
226                r: 0.98,
227                g: 0.74,
228                b: 0.15,
229            },
230            color_unfocused: DecorationBorderColor {
231                r: 0.12,
232                g: 0.12,
233                b: 0.12,
234            },
235        }
236    }
237}
238
239impl Default for DecorationsConfig {
240    fn default() -> Self {
241        Self {
242            border: PrimaryBorderConfig::default(),
243            secondary_border: SecondaryBorderConfig::default(),
244            resize_using_border: false,
245        }
246    }
247}
248
249#[derive(Clone, Copy, Debug, Eq, PartialEq)]
250pub enum PanToNewMode {
251    Never,
252    IfNeeded,
253    Always,
254}
255
256#[derive(Clone, Copy, Debug, Eq, PartialEq)]
257pub enum CloseRestorePanMode {
258    Never,
259    IfOffscreen,
260    Always,
261}
262
263#[derive(Clone, Copy, Debug, Eq, PartialEq)]
264pub enum ClickCollapsedOutsideFocusMode {
265    Ignore,
266    Activate,
267}
268
269#[derive(Clone, Copy, Debug, Eq, PartialEq)]
270pub enum ClickCollapsedPanMode {
271    Never,
272    IfOffscreen,
273    Always,
274}
275
276#[derive(Clone, Copy, Debug, Eq, PartialEq)]
277pub enum InputFocusMode {
278    Click,
279    Hover,
280}
281
282#[derive(Clone, Copy, Debug, Eq, PartialEq)]
283pub struct InputConfig {
284    pub repeat_rate: i32,
285    pub repeat_delay: i32,
286    pub focus_mode: InputFocusMode,
287}
288
289impl Default for InputConfig {
290    fn default() -> Self {
291        Self {
292            repeat_rate: 30,
293            repeat_delay: 500,
294            focus_mode: InputFocusMode::Click,
295        }
296    }
297}
298
299#[derive(Clone, Copy, Debug, PartialEq)]
300pub struct FocusRingConfig {
301    pub rx: f32,
302    pub ry: f32,
303    pub offset_x: f32,
304    pub offset_y: f32,
305}
306
307impl FocusRingConfig {
308    pub fn to_focus_ring(self) -> FocusRing {
309        FocusRing::new(self.rx, self.ry, self.offset_x, self.offset_y)
310    }
311}
312
313#[derive(Clone, Copy, Debug, PartialEq)]
314pub struct BearingsConfig {
315    pub show_distance: bool,
316    pub show_icons: bool,
317    pub fade_distance: f32,
318}
319
320#[derive(Clone, Debug, Eq, PartialEq)]
321pub struct CursorConfig {
322    pub theme: String,
323    pub size: u32,
324    pub hide_while_typing: bool,
325    pub hide_after_ms: u64,
326}
327
328impl Default for CursorConfig {
329    fn default() -> Self {
330        Self {
331            theme: "Adwaita".to_string(),
332            size: 24,
333            hide_while_typing: false,
334            hide_after_ms: 0,
335        }
336    }
337}
338
339#[derive(Clone, Debug, Eq, PartialEq)]
340pub struct FontConfig {
341    pub family: String,
342    pub size: u32,
343}
344
345impl Default for FontConfig {
346    fn default() -> Self {
347        Self {
348            family: "monospace".to_string(),
349            size: 11,
350        }
351    }
352}
353
354#[derive(Clone, Copy, Debug, Eq, PartialEq)]
355pub enum ClusterBloomDirection {
356    Clockwise,
357    CounterClockwise,
358}
359
360#[derive(Clone, Copy, Debug, Eq, PartialEq)]
361pub enum ClusterDefaultLayout {
362    Tiling,
363    Stacking,
364}
365
366impl ClusterDefaultLayout {
367    pub fn to_workspace_layout_kind(self) -> ClusterWorkspaceLayoutKind {
368        match self {
369            Self::Tiling => ClusterWorkspaceLayoutKind::Tiling,
370            Self::Stacking => ClusterWorkspaceLayoutKind::Stacking,
371        }
372    }
373}
374
375#[derive(Clone, Debug)]
376pub enum WindowRulePattern {
377    Exact(String),
378    Regex(Regex),
379}
380
381impl PartialEq for WindowRulePattern {
382    fn eq(&self, other: &Self) -> bool {
383        match (self, other) {
384            (Self::Exact(a), Self::Exact(b)) => a == b,
385            (Self::Regex(a), Self::Regex(b)) => a.as_str() == b.as_str(),
386            _ => false,
387        }
388    }
389}
390
391impl Eq for WindowRulePattern {}
392
393impl WindowRulePattern {
394    pub fn matches(&self, value: &str) -> bool {
395        match self {
396            Self::Exact(exact) => exact == value,
397            Self::Regex(regex) => regex.is_match(value),
398        }
399    }
400
401    pub fn as_str(&self) -> &str {
402        match self {
403            Self::Exact(exact) => exact.as_str(),
404            Self::Regex(regex) => regex.as_str(),
405        }
406    }
407}
408
409#[derive(Clone, Copy, Debug, Eq, PartialEq)]
410pub enum InitialWindowOverlapPolicy {
411    None,
412    ParentOnly,
413    All,
414}
415
416#[derive(Clone, Copy, Debug, Eq, PartialEq)]
417pub enum InitialWindowSpawnPlacement {
418    Center,
419    Adjacent,
420    ViewportCenter,
421    Cursor,
422    App,
423}
424
425#[derive(Clone, Copy, Debug, Eq, PartialEq)]
426pub enum InitialWindowClusterParticipation {
427    Layout,
428    Float,
429}
430
431#[derive(Clone, Debug, Eq, PartialEq)]
432pub struct WindowRule {
433    pub app_ids: Vec<WindowRulePattern>,
434    pub titles: Vec<WindowRulePattern>,
435    pub overlap_policy: InitialWindowOverlapPolicy,
436    pub spawn_placement: InitialWindowSpawnPlacement,
437    pub cluster_participation: InitialWindowClusterParticipation,
438}
439
440#[derive(Clone, Debug, PartialEq)]
441pub struct ViewportOutputConfig {
442    pub connector: String,
443    pub enabled: bool,
444    pub offset_x: i32,
445    pub offset_y: i32,
446    pub width: u32,
447    pub height: u32,
448    pub refresh_rate: Option<f64>,
449    pub transform_degrees: u16,
450    pub vrr: ViewportVrrMode,
451    pub focus_ring: Option<FocusRingConfig>,
452}
453
454#[derive(Clone, Copy, Debug, PartialEq, Eq)]
455pub enum ViewportVrrMode {
456    Off,
457    On,
458    OnDemand,
459}
460
461impl ViewportVrrMode {
462    pub fn as_str(self) -> &'static str {
463        match self {
464            Self::Off => "off",
465            Self::On => "on",
466            Self::OnDemand => "on-demand",
467        }
468    }
469
470    pub fn drm_enabled(self) -> bool {
471        !matches!(self, Self::Off)
472    }
473}