1use serde::Serialize;
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub enum Modifier {
46 Alt,
48 AltLeft,
50 AltRight,
52 Shift,
54 ShiftLeft,
56 ShiftRight,
58 Sym,
60 Function,
62 Ctrl,
64 CtrlLeft,
66 CtrlRight,
68 Meta,
71 MetaLeft,
73 MetaRight,
75 CapsLock,
77 NumLock,
79 ScrollLock,
81 Primary,
85}
86
87impl Modifier {
88 pub fn as_str(self) -> &'static str {
90 match self {
91 Self::Alt => "alt",
92 Self::AltLeft => "alt_left",
93 Self::AltRight => "alt_right",
94 Self::Shift => "shift",
95 Self::ShiftLeft => "shift_left",
96 Self::ShiftRight => "shift_right",
97 Self::Sym => "sym",
98 Self::Function => "function",
99 Self::Ctrl => "ctrl",
100 Self::CtrlLeft => "ctrl_left",
101 Self::CtrlRight => "ctrl_right",
102 Self::Meta => "meta",
103 Self::MetaLeft => "meta_left",
104 Self::MetaRight => "meta_right",
105 Self::CapsLock => "caps_lock",
106 Self::NumLock => "num_lock",
107 Self::ScrollLock => "scroll_lock",
108 Self::Primary => "primary",
109 }
110 }
111}
112
113impl Serialize for Modifier {
114 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
115 s.serialize_str(self.as_str())
116 }
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
127pub enum BindingAction {
128 #[default]
130 Down,
131 Up,
133 Repeat,
135}
136
137impl BindingAction {
138 pub fn as_str(self) -> &'static str {
140 match self {
141 Self::Down => "down",
142 Self::Up => "up",
143 Self::Repeat => "repeat",
144 }
145 }
146}
147
148impl Serialize for BindingAction {
149 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
150 s.serialize_str(self.as_str())
151 }
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
165pub struct Key(pub String);
166
167impl Key {
168 pub fn new(name: impl Into<String>) -> Self {
170 Self(name.into())
171 }
172}
173
174impl<S: Into<String>> From<S> for Key {
175 fn from(s: S) -> Self {
176 Self(s.into())
177 }
178}
179
180impl Serialize for Key {
181 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
182 s.serialize_str(&self.0)
183 }
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
190#[serde(rename_all = "snake_case")]
191pub enum Handedness {
192 #[default]
193 Right,
194 Left,
195}
196
197#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
201#[serde(rename_all = "snake_case")]
202pub enum PointerAcceleration {
203 Adaptive,
204 #[default]
205 None,
206}
207
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
212#[serde(rename_all = "snake_case")]
213pub enum CursorFocusMode {
214 #[default]
215 Hover,
216 Click,
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
223#[serde(rename_all = "snake_case")]
224pub enum TouchpadClickMode {
225 #[default]
226 None,
227 AreaToClick,
228 FingerCount,
229}
230
231#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
235#[serde(rename_all = "snake_case")]
236pub enum TouchpadScrollMode {
237 #[default]
238 None,
239 TwoFingerScroll,
240 EdgeScroll,
241 ButtonDownScroll,
242}
243
244#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
248#[serde(rename_all = "snake_case")]
249pub enum AnimationPartType {
250 #[default]
251 Disabled,
252 Slide,
253 Grow,
254 Shrink,
255 Fade,
256}
257
258#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
262#[serde(rename_all = "snake_case")]
263pub enum EasingFunction {
264 #[default]
265 Linear,
266 EaseInSine,
267 EaseOutSine,
268 EaseInOutSine,
269 EaseInQuad,
270 EaseOutQuad,
271 EaseInOutQuad,
272 EaseInCubic,
273 EaseOutCubic,
274 EaseInOutCubic,
275 EaseInQuart,
276 EaseOutQuart,
277 EaseInOutQuart,
278 EaseInQuint,
279 EaseOutQuint,
280 EaseInOutQuint,
281 EaseInExpo,
282 EaseOutExpo,
283 EaseInOutExpo,
284 EaseInCirc,
285 EaseOutCirc,
286 EaseInOutCirc,
287 EaseInBack,
288 EaseOutBack,
289 EaseInOutBack,
290 EaseInElastic,
291 EaseOutElastic,
292 EaseInOutElastic,
293 EaseInBounce,
294 EaseOutBounce,
295 EaseInOutBounce,
296}
297
298#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
302#[serde(rename_all = "snake_case")]
303pub enum AnimationEvent {
304 #[default]
305 WindowOpen,
306 WindowMove,
307 WindowClose,
308 WorkspaceSwitch,
309}
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize)]
315#[serde(rename_all = "snake_case")]
316pub enum AnimationKind {
317 #[default]
318 BuiltIn,
319 Plugin,
320}
321
322#[derive(Debug, Clone, Default, Serialize)]
326pub struct Gaps {
327 pub x: i32,
328 pub y: i32,
329}
330
331#[derive(Debug, Clone, Serialize)]
333pub struct CustomKeyAction {
334 pub action: BindingAction,
336 pub modifiers: Vec<Modifier>,
338 pub key: Key,
340 pub command: String,
342}
343
344#[derive(Debug, Clone, Serialize)]
346pub struct BuiltInKeyCommandOverride {
347 pub name: String,
349 pub action: BindingAction,
351 pub modifiers: Vec<Modifier>,
353 pub key: Key,
355}
356
357#[derive(Debug, Clone, Default, Serialize)]
359pub struct StartupApp {
360 pub command: String,
361 #[serde(skip_serializing_if = "is_false")]
362 pub restart_on_death: bool,
363 #[serde(skip_serializing_if = "is_false")]
364 pub no_startup_id: bool,
365 #[serde(skip_serializing_if = "is_false")]
366 pub should_halt_compositor_on_death: bool,
367 #[serde(skip_serializing_if = "is_false")]
368 pub in_systemd_scope: bool,
369}
370
371#[derive(Debug, Clone, Default, Serialize)]
373pub struct EnvironmentVariable {
374 pub key: String,
375 pub value: String,
376}
377
378#[derive(Debug, Clone, Default, Serialize)]
380pub struct BorderConfig {
381 pub size: i32,
382 pub radius: f32,
383 pub color: String,
385 pub focus_color: String,
387}
388
389#[derive(Debug, Clone, Default, Serialize)]
391pub struct WorkspaceConfig {
392 #[serde(skip_serializing_if = "Option::is_none")]
393 pub number: Option<i32>,
394 #[serde(skip_serializing_if = "Option::is_none")]
395 pub name: Option<String>,
396}
397
398#[derive(Debug, Clone, Serialize)]
400pub struct DragAndDropConfiguration {
401 pub enabled: bool,
402 #[serde(skip_serializing_if = "Vec::is_empty")]
404 pub modifiers: Vec<Modifier>,
405}
406
407impl Default for DragAndDropConfiguration {
408 fn default() -> Self {
409 Self {
410 enabled: true,
411 modifiers: Vec::new(),
412 }
413 }
414}
415
416#[derive(Debug, Clone, Default, Serialize)]
418pub struct BuiltInAnimationPart {
419 #[serde(rename = "type")]
421 pub type_: AnimationPartType,
422 pub function: EasingFunction,
424 #[serde(skip_serializing_if = "Option::is_none")]
425 pub c1: Option<f32>,
426 #[serde(skip_serializing_if = "Option::is_none")]
427 pub c2: Option<f32>,
428 #[serde(skip_serializing_if = "Option::is_none")]
429 pub c3: Option<f32>,
430 #[serde(skip_serializing_if = "Option::is_none")]
431 pub c4: Option<f32>,
432 #[serde(skip_serializing_if = "Option::is_none")]
433 pub n1: Option<f32>,
434 #[serde(skip_serializing_if = "Option::is_none")]
435 pub d1: Option<f32>,
436}
437
438#[derive(Debug, Clone, Default, Serialize)]
440pub struct AnimationDefinition {
441 pub event: AnimationEvent,
443 #[serde(rename = "type")]
445 pub type_: AnimationKind,
446 #[serde(skip_serializing_if = "Option::is_none")]
448 pub duration: Option<f32>,
449 #[serde(skip_serializing_if = "Vec::is_empty")]
451 pub parts: Vec<BuiltInAnimationPart>,
452}
453
454#[derive(Debug, Clone, Default, Serialize)]
456pub struct MouseConfiguration {
457 #[serde(skip_serializing_if = "Option::is_none")]
459 pub handedness: Option<Handedness>,
460 #[serde(skip_serializing_if = "Option::is_none")]
462 pub acceleration: Option<PointerAcceleration>,
463 #[serde(skip_serializing_if = "Option::is_none")]
464 pub acceleration_bias: Option<f64>,
465 #[serde(skip_serializing_if = "Option::is_none")]
466 pub vscroll_speed: Option<f64>,
467 #[serde(skip_serializing_if = "Option::is_none")]
468 pub hscroll_speed: Option<f64>,
469}
470
471#[derive(Debug, Clone, Default, Serialize)]
473pub struct KeymapConfiguration {
474 pub language: String,
475 #[serde(skip_serializing_if = "Option::is_none")]
476 pub variant: Option<String>,
477 #[serde(skip_serializing_if = "Vec::is_empty")]
478 pub options: Vec<String>,
479}
480
481#[derive(Debug, Clone, Default, Serialize)]
483pub struct KeyboardConfiguration {
484 #[serde(skip_serializing_if = "Option::is_none")]
485 pub repeat_delay: Option<i32>,
486 #[serde(skip_serializing_if = "Option::is_none")]
487 pub repeat_rate: Option<i32>,
488 #[serde(skip_serializing_if = "Option::is_none")]
489 pub keymap: Option<KeymapConfiguration>,
490}
491
492#[derive(Debug, Clone, Default, Serialize)]
494pub struct HoverClickConfiguration {
495 pub enabled: bool,
496 #[serde(skip_serializing_if = "Option::is_none", rename = "hover_duration")]
498 pub hover_duration_ms: Option<u32>,
499 #[serde(skip_serializing_if = "Option::is_none")]
500 pub cancel_displacement_threshold: Option<i32>,
501 #[serde(skip_serializing_if = "Option::is_none")]
502 pub reclick_displacement_threshold: Option<i32>,
503}
504
505#[derive(Debug, Clone, Default, Serialize)]
507pub struct SimulatedSecondaryClickConfiguration {
508 pub enabled: bool,
509 #[serde(skip_serializing_if = "Option::is_none", rename = "hold_duration")]
511 pub hold_duration_ms: Option<u32>,
512 #[serde(skip_serializing_if = "Option::is_none")]
513 pub displacement_threshold: Option<i32>,
514}
515
516#[derive(Debug, Clone, Default, Serialize)]
518pub struct OutputFilterConfiguration {
519 #[serde(skip_serializing_if = "Option::is_none")]
520 pub shader_path: Option<String>,
521}
522
523#[derive(Debug, Clone, Default, Serialize)]
525pub struct CursorConfiguration {
526 #[serde(skip_serializing_if = "Option::is_none")]
527 pub scale: Option<f32>,
528 #[serde(skip_serializing_if = "Option::is_none")]
530 pub focus_mode: Option<CursorFocusMode>,
531}
532
533#[derive(Debug, Clone, Default, Serialize)]
535pub struct SlowKeysConfiguration {
536 pub enabled: bool,
537 #[serde(skip_serializing_if = "Option::is_none", rename = "hold_delay")]
539 pub hold_delay_ms: Option<u32>,
540}
541
542#[derive(Debug, Clone, Default, Serialize)]
544pub struct StickyKeysConfiguration {
545 pub enabled: bool,
546 #[serde(skip_serializing_if = "Option::is_none")]
547 pub should_disable_if_two_keys_are_pressed_together: Option<bool>,
548}
549
550#[derive(Debug, Clone, Default, Serialize)]
552pub struct TouchpadConfiguration {
553 #[serde(skip_serializing_if = "Option::is_none")]
554 pub disable_while_typing: Option<bool>,
555 #[serde(skip_serializing_if = "Option::is_none")]
556 pub disable_with_external_mouse: Option<bool>,
557 #[serde(skip_serializing_if = "Option::is_none")]
558 pub acceleration_bias: Option<f64>,
559 #[serde(skip_serializing_if = "Option::is_none")]
560 pub vscroll_speed: Option<f64>,
561 #[serde(skip_serializing_if = "Option::is_none")]
562 pub hscroll_speed: Option<f64>,
563 #[serde(skip_serializing_if = "Option::is_none")]
564 pub tap_to_click: Option<bool>,
565 #[serde(skip_serializing_if = "Option::is_none")]
566 pub middle_mouse_button_emulation: Option<bool>,
567 #[serde(skip_serializing_if = "Option::is_none")]
569 pub click_mode: Option<TouchpadClickMode>,
570 #[serde(skip_serializing_if = "Option::is_none")]
572 pub scroll_mode: Option<TouchpadScrollMode>,
573}
574
575#[derive(Debug, Clone, Default, Serialize)]
577pub struct MagnifierConfiguration {
578 pub enabled: bool,
579 #[serde(skip_serializing_if = "Option::is_none")]
580 pub scale: Option<f32>,
581 #[serde(skip_serializing_if = "Option::is_none")]
582 pub scale_increment: Option<f32>,
583 #[serde(skip_serializing_if = "Option::is_none")]
584 pub width: Option<i32>,
585 #[serde(skip_serializing_if = "Option::is_none")]
586 pub height: Option<i32>,
587 #[serde(skip_serializing_if = "Option::is_none")]
588 pub size_increment: Option<i32>,
589}
590
591#[derive(Debug, Clone, Default, Serialize)]
600pub struct Configuration {
601 #[serde(skip_serializing_if = "Option::is_none", rename = "action_key")]
603 pub primary_modifier: Option<Modifier>,
604
605 #[serde(skip_serializing_if = "Option::is_none", rename = "custom_actions")]
607 pub custom_key_actions: Option<Vec<CustomKeyAction>>,
608
609 #[serde(skip_serializing_if = "Option::is_none")]
611 pub default_action_overrides: Option<Vec<BuiltInKeyCommandOverride>>,
612
613 #[serde(skip_serializing_if = "Option::is_none")]
615 pub inner_gaps: Option<Gaps>,
616
617 #[serde(skip_serializing_if = "Option::is_none")]
619 pub outer_gaps: Option<Gaps>,
620
621 #[serde(skip_serializing_if = "Option::is_none")]
623 pub startup_apps: Option<Vec<StartupApp>>,
624
625 #[serde(skip_serializing_if = "Option::is_none")]
627 pub terminal: Option<String>,
628
629 #[serde(skip_serializing_if = "Option::is_none")]
631 pub resize_jump: Option<i32>,
632
633 #[serde(skip_serializing_if = "Option::is_none")]
635 pub environment_variables: Option<Vec<EnvironmentVariable>>,
636
637 #[serde(skip_serializing_if = "Option::is_none")]
639 pub border: Option<BorderConfig>,
640
641 #[serde(skip_serializing_if = "Option::is_none")]
643 pub workspaces: Option<Vec<WorkspaceConfig>>,
644
645 #[serde(skip_serializing_if = "Option::is_none")]
647 pub animations: Option<Vec<AnimationDefinition>>,
648
649 #[serde(skip_serializing_if = "Option::is_none")]
651 pub enable_animations: Option<bool>,
652
653 #[serde(skip_serializing_if = "Option::is_none")]
656 pub move_modifier: Option<Vec<Modifier>>,
657
658 #[serde(skip_serializing_if = "Option::is_none")]
660 pub drag_and_drop: Option<DragAndDropConfiguration>,
661
662 #[serde(skip_serializing_if = "Option::is_none")]
664 pub mouse: Option<MouseConfiguration>,
665
666 #[serde(skip_serializing_if = "Option::is_none")]
668 pub touchpad: Option<TouchpadConfiguration>,
669
670 #[serde(skip_serializing_if = "Option::is_none")]
672 pub keyboard: Option<KeyboardConfiguration>,
673
674 #[serde(skip_serializing_if = "Option::is_none")]
676 pub hover_click: Option<HoverClickConfiguration>,
677
678 #[serde(skip_serializing_if = "Option::is_none")]
680 pub simulated_secondary_click: Option<SimulatedSecondaryClickConfiguration>,
681
682 #[serde(skip_serializing_if = "Option::is_none")]
684 pub output_filter: Option<OutputFilterConfiguration>,
685
686 #[serde(skip_serializing_if = "Option::is_none")]
688 pub cursor: Option<CursorConfiguration>,
689
690 #[serde(skip_serializing_if = "Option::is_none")]
692 pub slow_keys: Option<SlowKeysConfiguration>,
693
694 #[serde(skip_serializing_if = "Option::is_none")]
696 pub sticky_keys: Option<StickyKeysConfiguration>,
697
698 #[serde(skip_serializing_if = "Option::is_none")]
700 pub magnifier: Option<MagnifierConfiguration>,
701
702 #[serde(skip_serializing_if = "Option::is_none")]
704 pub workspace_back_and_forth: Option<bool>,
705}
706
707fn is_false(v: &bool) -> bool {
708 !v
709}