Commit ad802fd23506
tarball4 files changed+38-16
@@ -277,6 +277,7 @@ pub enum Reply {
277277
pub enum Answer {278278
State(State),279279
Version(String),280
+ Warnings(Vec<String>),280281
}281282
282283
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]@@ -8,29 +8,39 @@ use smithay::reexports::calloop::{Interest, Mode, PostAction};
88
use std::os::fd::{FromRawFd, OwnedFd, RawFd};99
use std::process::{Child, Stdio};1010
11
-pub struct Binds(Vec<(Mods, Keysym, Command)>);11
+pub struct Binds {12
+ binds: Vec<(Mods, Keysym, Command)>,13
+ pub warnings: Vec<String>,14
+}1215
1316
impl Binds {1417
pub fn new(config: &Config) -> Self {15
- let binds = config16
- .binds17
- .iter()18
- .filter_map(|b| {19
- let sym = xkb::keysym_from_name(&b.key, xkb::KEYSYM_CASE_INSENSITIVE);20
- if sym.raw() == xkb::keysyms::KEY_NoSymbol {21
- tracing::warn!("bind: unknown key {:?}", b.key);22
- return None;23
- }24
- Some((b.mods, sym, b.command.clone()))25
- })26
- .collect();27
- Self(binds)18
+ let mut warnings = Vec::new();19
+ let mut binds: Vec<(Mods, Keysym, Command)> = Vec::new();20
+ for b in &config.binds {21
+ let sym = xkb::keysym_from_name(&b.key, xkb::KEYSYM_CASE_INSENSITIVE);22
+ if sym.raw() == xkb::keysyms::KEY_NoSymbol {23
+ warnings.push(format!("bind: unknown key {:?}", b.key));24
+ continue;25
+ }26
+ if binds.iter().any(|(m, s, _)| *m == b.mods && *s == sym) {27
+ warnings.push(format!(28
+ "bind: {:?} with {:?} duplicates an earlier bind, which wins",29
+ b.key, b.mods30
+ ));31
+ }32
+ binds.push((b.mods, sym, b.command.clone()));33
+ }34
+ for w in &warnings {35
+ tracing::warn!("{w}");36
+ }37
+ Self { binds, warnings }2838
}2939
3040
/// Matches on the unshifted keysyms so `Mod+Shift+1` means the 1 key.3141
pub fn find(&self, mods: &ModifiersState, syms: &[Keysym]) -> Option<Command> {3242
let held = held(mods);33
- self.043
+ self.binds3444
.iter()3545
.find(|(m, sym, _)| *m == held && syms.contains(sym))3646
.map(|(_, _, c)| c.clone())@@ -216,10 +226,13 @@ impl State {
216226
/// running config untouched.217227
pub fn reload(&mut self) -> Result<(), String> {218228
let loaded = Config::load(self.settings.path.as_deref()).map_err(|e| e.to_string())?;229
+ let mut warnings = loaded.warnings.clone();219230
let config = warn_config(loaded);220231
let keyboard_changed = config.keyboard != self.settings.config.keyboard;221232
let input_changed = config.input != self.settings.config.input;222233
self.settings.binds = Binds::new(&config);234
+ warnings.extend(self.settings.binds.warnings.iter().cloned());235
+ self.settings.warnings = warnings;223236
self.wm.layout.gaps = crate::state::gaps(&config);224237
self.wm.layout.autotile = config.general.autotile;225238
self.wm.anim.settings = config.animation.clone();@@ -104,7 +104,12 @@ fn handle_line(state: &mut State, stream: &UnixStream, line: &[u8]) -> Option<En
104104
return Some(Envelope::new(id, Reply::Error(msg)));105105
}106106
let reply = match req.body {107
- Request::Run(cmd) => match state.run(cmd) {107
+ Request::Run(cmd) => match state.run(cmd.clone()) {108
+ Ok(())109
+ if cmd == monolith_ipc::Command::Reload && !state.settings.warnings.is_empty() =>110
+ {111
+ Reply::Ok(Some(Answer::Warnings(state.settings.warnings.clone())))112
+ }108113
Ok(()) => Reply::Ok(None),109114
Err(e) => Reply::Error(e),110115
},@@ -245,6 +250,7 @@ fn talk(request: Request) -> ExitCode {
245250
Reply::Ok(None) => {}246251
Reply::Ok(Some(answer)) => match answer {247252
Answer::Version(v) => println!("{v}"),253
+ Answer::Warnings(ws) => ws.iter().for_each(|w| eprintln!("config: {w}")),248254
Answer::State(s) => {249255
println!("{}", serde_json::to_string_pretty(&s).unwrap_or_default())250256
}@@ -97,6 +97,7 @@ pub struct Settings {
9797
pub config: Config,9898
pub path: Option<PathBuf>,9999
pub binds: Binds,100
+ pub warnings: Vec<String>,100101
}101102
102103
impl State {@@ -171,6 +172,7 @@ impl State {
171172
binds: Binds::new(&config),172173
config,173174
path: config_path,175
+ warnings: Vec::new(),174176
},175177
renderer,176178
wm: Wm::new(layout, Animator::new(animation)),