Skip to main content

hyprshell_exec_lib/
binds.rs

1use anyhow::Context;
2use core_lib::binds::ExecBind;
3use core_lib::{LAUNCHER_NAMESPACE, OVERVIEW_NAMESPACE, SWITCH_NAMESPACE};
4use hyprland::bind_new::{Binding, Flag, Mod};
5use hyprland::config::binds;
6use hyprland::dispatch::DispatchType;
7use hyprland::dispatch_new::Dispatch;
8use hyprland::keyword::Keyword;
9use hyprland::window_rule::{LayerEffect, LayerMatch, LayerRule};
10use tracing::{trace, warn};
11
12pub fn apply_layerrules() -> anyhow::Result<()> {
13    if let Err(e) = apply_layerrules_lua() {
14        warn!("Failed to apply layerrules: {}, trying legacy syntax", e);
15        return apply_layerrules_legacy();
16    };
17    Ok(())
18}
19
20pub fn apply_layerrules_lua() -> anyhow::Result<()> {
21    // TODO add option to enable blur
22    let rules = vec![
23        LayerRule {
24            name: None,
25            r#match: vec![LayerMatch::Namespace(LAUNCHER_NAMESPACE.into())],
26            effects: vec![LayerEffect::NoAnim(true), LayerEffect::Xray(false)],
27        },
28        LayerRule {
29            name: None,
30            r#match: vec![LayerMatch::Namespace(OVERVIEW_NAMESPACE.into())],
31            effects: vec![LayerEffect::NoAnim(true), LayerEffect::Xray(false)],
32        },
33        LayerRule {
34            name: None,
35            r#match: vec![LayerMatch::Namespace(SWITCH_NAMESPACE.into())],
36            effects: vec![
37                LayerEffect::NoAnim(true),
38                LayerEffect::Xray(false),
39                LayerEffect::DimAround(true),
40            ],
41        },
42    ];
43
44    for rule in rules {
45        rule.apply()?;
46    }
47    Ok(())
48}
49
50pub fn apply_layerrules_legacy() -> anyhow::Result<()> {
51    // TODO add option to enable blur
52    Keyword::set("layerrule", format!("noanim, {LAUNCHER_NAMESPACE}"))?;
53    Keyword::set("layerrule", format!("xray 0, {LAUNCHER_NAMESPACE}"))?;
54
55    Keyword::set("layerrule", format!("noanim, {OVERVIEW_NAMESPACE}"))?;
56    Keyword::set("layerrule", format!("xray 0, {OVERVIEW_NAMESPACE}"))?;
57
58    Keyword::set("layerrule", format!("noanim, {SWITCH_NAMESPACE}"))?;
59    Keyword::set("layerrule", format!("dimaround, {SWITCH_NAMESPACE}"))?;
60    Keyword::set("layerrule", format!("xray 0, {SWITCH_NAMESPACE}"))?;
61    Ok(())
62}
63
64pub fn apply_exec_bind(bind: &ExecBind) -> anyhow::Result<()> {
65    if let Err(e) = apply_exec_bind_lua(bind) {
66        warn!("Failed to apply keybinds: {}, trying legacy syntax", e);
67        return apply_exec_bind_legacy(bind);
68    };
69    Ok(())
70}
71
72pub fn apply_exec_bind_lua(bind: &ExecBind) -> anyhow::Result<()> {
73    let binds: Vec<_> = bind
74        .mods
75        .iter()
76        .filter_map(|m| match m.to_lowercase().as_str() {
77            "alt" => Some(Mod::Alt),
78            "control" | "ctrl" => Some(Mod::Ctrl),
79            "super" | "win" => Some(Mod::Super),
80            "shift" => Some(Mod::Shift),
81            _ => {
82                warn!("unknown mod: {m}");
83                None
84            }
85        })
86        .collect();
87
88    let binding = Binding {
89        mods: binds,
90        key: bind.key.to_string(),
91        flags: if bind.release {
92            vec![
93                Flag::Release,
94                Flag::Transparent,
95                Flag::AutoConsuming,
96                Flag::Description(bind.desc.clone()),
97            ]
98        } else {
99            vec![
100                Flag::AutoConsuming,
101                Flag::Repeating,
102                Flag::Description(bind.desc.clone()),
103            ]
104        },
105        dispatcher: Dispatch::ExecCmd(bind.exec.to_string(), None),
106    };
107    trace!("binding exec: {binding:?}");
108    binding.unbind()?;
109    binding.bind()?;
110    Ok(())
111}
112
113pub fn apply_exec_bind_legacy(bind: &ExecBind) -> anyhow::Result<()> {
114    let mods = bind
115        .mods
116        .iter()
117        .filter_map(|m| match m.to_lowercase().as_str() {
118            "alt" => Some(binds::Mod::ALT),
119            "control" | "ctrl" => Some(binds::Mod::CTRL),
120            "super" | "win" => Some(binds::Mod::SUPER),
121            "shift" => Some(binds::Mod::SHIFT),
122            _ => {
123                warn!("unknown mod: {m}");
124                None
125            }
126        })
127        .collect::<Vec<_>>();
128    let binding = binds::Binding {
129        mods: mods.as_slice(),
130        key: binds::Key::Key(&bind.key),
131        flags: &vec![],
132        dispatcher: DispatchType::Exec(&bind.exec),
133    };
134    trace!("binding exec: {binding:?}");
135    binds::Binder::bind(binding).with_context(|| format!("binding exec failed: {bind:?}"))?;
136    Ok(())
137}