hyprshell_exec_lib/
binds.rs1use 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 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 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}