Warn on malformed arm_auto_apply regex instead of silently falling through
Both window_match.class and window_match.title patterns are now logged as warnings when regex::Regex::new returns Err. Before, .ok() silently swallowed compile errors and treated a bad pattern as 'not configured', which collapsed back to the original bug: any open window could fire layout-apply. The no-configured-patterns fallback (accept a window with a non-empty class) is preserved for users who haven't set window_match at all.
This commit is contained in:
parent
0ad3e3335e
commit
91cfee9609
28
src/gui.rs
28
src/gui.rs
@ -1633,20 +1633,40 @@ impl App {
|
|||||||
let profile_path = self.path.clone();
|
let profile_path = self.path.clone();
|
||||||
let allow = self.allow_layout;
|
let allow = self.allow_layout;
|
||||||
// Compile the profile's window_match patterns once, outside the
|
// Compile the profile's window_match patterns once, outside the
|
||||||
// poll loop. If a pattern is malformed we treat it as "not
|
// poll loop. Malformed patterns are logged as a warning rather
|
||||||
// configured" rather than crashing the auto-apply thread.
|
// than silently treated as "no pattern" — the latter would make
|
||||||
|
// a typo in the YAML fall back to firing on ANY client, which
|
||||||
|
// is the exact bug we fixed in 7c94417.
|
||||||
let class_pat = self
|
let class_pat = self
|
||||||
.profile
|
.profile
|
||||||
.window_match
|
.window_match
|
||||||
.class
|
.class
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.and_then(|p| regex::Regex::new(p).ok());
|
.and_then(|p| match regex::Regex::new(p) {
|
||||||
|
Ok(re) => Some(re),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(
|
||||||
|
"arm_auto_apply: invalid window_match.class regex {:?}: {}",
|
||||||
|
p, e
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
let title_pat = self
|
let title_pat = self
|
||||||
.profile
|
.profile
|
||||||
.window_match
|
.window_match
|
||||||
.title
|
.title
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.and_then(|p| regex::Regex::new(p).ok());
|
.and_then(|p| match regex::Regex::new(p) {
|
||||||
|
Ok(re) => Some(re),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(
|
||||||
|
"arm_auto_apply: invalid window_match.title regex {:?}: {}",
|
||||||
|
p, e
|
||||||
|
);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
let any_pattern = class_pat.is_some() || title_pat.is_some();
|
let any_pattern = class_pat.is_some() || title_pat.is_some();
|
||||||
std::thread::Builder::new()
|
std::thread::Builder::new()
|
||||||
.name("enboxer-auto-apply".into())
|
.name("enboxer-auto-apply".into())
|
||||||
|
|||||||
@ -1022,7 +1022,20 @@ async fn execute(actions: Vec<Action>, slots: &[(u32, Client)]) -> Result<()> {
|
|||||||
};
|
};
|
||||||
for id in ids {
|
for id in ids {
|
||||||
if let Some((_, c)) = slots.iter().find(|(s, _)| *s == id) {
|
if let Some((_, c)) = slots.iter().find(|(s, _)| *s == id) {
|
||||||
hypr::deliver_key(c, &key, parsed_state).await?;
|
// Per-slot failures must NOT abort the rest of the
|
||||||
|
// chain. For example, a smart_interact (CTM on -> Alt+J
|
||||||
|
// -> sleep -> CTM off) must keep going through every
|
||||||
|
// captured slot even if one wlr-keyboard barf means
|
||||||
|
// Alt+J never lands on that client — otherwise CTM
|
||||||
|
// can stay on for the survivors and the user has to
|
||||||
|
// manually reset it.
|
||||||
|
if let Err(e) =
|
||||||
|
hypr::deliver_key(c, &key, parsed_state).await
|
||||||
|
{
|
||||||
|
tracing::warn!(
|
||||||
|
"deliver_key slot {id} key {key:?} failed: {e}"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user