Skip to content

Commit

Permalink
fix(wm): avoid focused ws rule enforcement deadlock
Browse files Browse the repository at this point in the history
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
  • Loading branch information
LGUG2Z committed Jan 5, 2025
1 parent 4b30cec commit 44716fd
Showing 1 changed file with 62 additions and 57 deletions.
119 changes: 62 additions & 57 deletions komorebi/src/window_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,53 +720,69 @@ impl WindowManager {
.ok_or_else(|| anyhow!("there is no monitor with that index"))?
.focused_workspace_idx();

let workspace_matching_rules = WORKSPACE_MATCHING_RULES.lock();
let regex_identifiers = REGEX_IDENTIFIERS.lock();
// Go through all the monitors and workspaces
for (i, monitor) in self.monitors().iter().enumerate() {
for (j, workspace) in monitor.workspaces().iter().enumerate() {
// And all the visible windows (at the top of a container)
for window in workspace.visible_windows().into_iter().flatten() {
let mut already_moved_window_handles = 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 {
let matched = match &rule.matching_rule {
MatchingRule::Simple(r) => should_act_individual(
&title,
&exe_name,
&class,
&path,
r,
&regex_identifiers,
),
MatchingRule::Composite(r) => {
let mut composite_results = vec![];
for identifier in r {
composite_results.push(should_act_individual(
&title,
&exe_name,
&class,
&path,
identifier,
&regex_identifiers,
));
// scope mutex locks to avoid deadlock if should_update_focused_workspace evaluates to true
// at the end of this function
{
let workspace_matching_rules = WORKSPACE_MATCHING_RULES.lock();
let regex_identifiers = REGEX_IDENTIFIERS.lock();
// Go through all the monitors and workspaces
for (i, monitor) in self.monitors().iter().enumerate() {
for (j, workspace) in monitor.workspaces().iter().enumerate() {
// And all the visible windows (at the top of a container)
for window in workspace.visible_windows().into_iter().flatten() {
let mut already_moved_window_handles =
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 {
let matched = match &rule.matching_rule {
MatchingRule::Simple(r) => should_act_individual(
&title,
&exe_name,
&class,
&path,
r,
&regex_identifiers,
),
MatchingRule::Composite(r) => {
let mut composite_results = vec![];
for identifier in r {
composite_results.push(should_act_individual(
&title,
&exe_name,
&class,
&path,
identifier,
&regex_identifiers,
));
}

composite_results.iter().all(|&x| x)
}

composite_results.iter().all(|&x| x)
}
};

if matched {
let floating = workspace.floating_windows().contains(window);

if rule.initial_only {
if !already_moved_window_handles.contains(&window.hwnd) {
already_moved_window_handles.insert(window.hwnd);

};

if matched {
let floating = workspace.floating_windows().contains(window);

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(
&window.title()?,
window.hwnd,
Expand All @@ -778,17 +794,6 @@ impl WindowManager {
&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,
);
}
}
}
Expand Down

0 comments on commit 44716fd

Please sign in to comment.