fix(wm): avoid focused ws rule enforcement deadlock

This commit adds mutex lock scoping in
WindowManager::enforce_workspace_rule to avoid a deadlock when
should_update_focused_workspace evaluates to true.

fix #1212
This commit is contained in:
LGUG2Z
2025-01-04 09:39:04 -08:00
parent 4b30cecba9
commit 44716fdc98
+58 -53
View File
@@ -720,53 +720,69 @@ impl WindowManager {
.ok_or_else(|| anyhow!("there is no monitor with that index"))? .ok_or_else(|| anyhow!("there is no monitor with that index"))?
.focused_workspace_idx(); .focused_workspace_idx();
let workspace_matching_rules = WORKSPACE_MATCHING_RULES.lock(); // scope mutex locks to avoid deadlock if should_update_focused_workspace evaluates to true
let regex_identifiers = REGEX_IDENTIFIERS.lock(); // at the end of this function
// Go through all the monitors and workspaces {
for (i, monitor) in self.monitors().iter().enumerate() { let workspace_matching_rules = WORKSPACE_MATCHING_RULES.lock();
for (j, workspace) in monitor.workspaces().iter().enumerate() { let regex_identifiers = REGEX_IDENTIFIERS.lock();
// And all the visible windows (at the top of a container) // Go through all the monitors and workspaces
for window in workspace.visible_windows().into_iter().flatten() { for (i, monitor) in self.monitors().iter().enumerate() {
let mut already_moved_window_handles = self.already_moved_window_handles.lock(); for (j, workspace) in monitor.workspaces().iter().enumerate() {
let exe_name = window.exe()?; // And all the visible windows (at the top of a container)
let title = window.title()?; for window in workspace.visible_windows().into_iter().flatten() {
let class = window.class()?; let mut already_moved_window_handles =
let path = window.path()?; self.already_moved_window_handles.lock();
let exe_name = window.exe()?;
let title = window.title()?;
let class = window.class()?;
let path = window.path()?;
for rule in &*workspace_matching_rules { for rule in &*workspace_matching_rules {
let matched = match &rule.matching_rule { let matched = match &rule.matching_rule {
MatchingRule::Simple(r) => should_act_individual( MatchingRule::Simple(r) => should_act_individual(
&title, &title,
&exe_name, &exe_name,
&class, &class,
&path, &path,
r, r,
&regex_identifiers, &regex_identifiers,
), ),
MatchingRule::Composite(r) => { MatchingRule::Composite(r) => {
let mut composite_results = vec![]; let mut composite_results = vec![];
for identifier in r { for identifier in r {
composite_results.push(should_act_individual( composite_results.push(should_act_individual(
&title, &title,
&exe_name, &exe_name,
&class, &class,
&path, &path,
identifier, identifier,
&regex_identifiers, &regex_identifiers,
)); ));
}
composite_results.iter().all(|&x| x)
} }
};
composite_results.iter().all(|&x| x) if matched {
} let floating = workspace.floating_windows().contains(window);
};
if matched { if rule.initial_only {
let floating = workspace.floating_windows().contains(window); if !already_moved_window_handles.contains(&window.hwnd) {
already_moved_window_handles.insert(window.hwnd);
if rule.initial_only {
if !already_moved_window_handles.contains(&window.hwnd) {
already_moved_window_handles.insert(window.hwnd);
self.add_window_handle_to_move_based_on_workspace_rule(
&window.title()?,
window.hwnd,
i,
j,
rule.monitor_index,
rule.workspace_index,
floating,
&mut to_move,
);
}
} else {
self.add_window_handle_to_move_based_on_workspace_rule( self.add_window_handle_to_move_based_on_workspace_rule(
&window.title()?, &window.title()?,
window.hwnd, window.hwnd,
@@ -778,17 +794,6 @@ impl WindowManager {
&mut to_move, &mut to_move,
); );
} }
} else {
self.add_window_handle_to_move_based_on_workspace_rule(
&window.title()?,
window.hwnd,
i,
j,
rule.monitor_index,
rule.workspace_index,
floating,
&mut to_move,
);
} }
} }
} }