Skip to content

Commit 6a1721b

Browse files
committed
fix: use bind_to_monitor from config when focusing or moving to a workspace
1 parent 564e316 commit 6a1721b

File tree

7 files changed

+91
-52
lines changed

7 files changed

+91
-52
lines changed

packages/wm/src/common/commands/reload_config.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ fn update_workspace_configs(
7777
// When the workspace config is not found, the current name of the
7878
// workspace has been removed. So, we reassign the first suitable
7979
// workspace config to the workspace.
80-
config.workspace_config_for_monitor(&monitor, &workspaces)
80+
config
81+
.workspace_config_for_monitor(&monitor, &workspaces)
82+
.or_else(|| config.next_inactive_workspace_config(&workspaces))
8183
});
8284

8385
match workspace_config {

packages/wm/src/monitors/commands/add_monitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ pub fn add_monitor(
3737
});
3838

3939
// Activate a workspace on the newly added monitor.
40-
activate_workspace(None, &monitor, state, config)
40+
activate_workspace(None, Some(monitor), state, config)
4141
.context("At least 1 workspace is required per monitor.")?;
4242

4343
Ok(())

packages/wm/src/user_config.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -287,21 +287,27 @@ impl UserConfig {
287287
let inactive_configs =
288288
self.inactive_workspace_configs(active_workspaces);
289289

290-
let bound_config = inactive_configs.iter().find(|&config| {
290+
inactive_configs.into_iter().find(|&config| {
291291
config
292292
.bind_to_monitor
293293
.as_ref()
294294
.map(|monitor_index| monitor.index() == *monitor_index as usize)
295295
.unwrap_or(false)
296-
});
296+
})
297+
}
297298

298-
// Get the first workspace config that isn't bound to a monitor.
299-
bound_config
300-
.or(
301-
inactive_configs
302-
.iter()
303-
.find(|config| config.bind_to_monitor.is_none()),
304-
)
299+
/// Gets the first inactive workspace config, prioritizing configs that
300+
/// don't have a monitor binding.
301+
pub fn next_inactive_workspace_config(
302+
&self,
303+
active_workspaces: &Vec<Workspace>,
304+
) -> Option<&WorkspaceConfig> {
305+
let inactive_configs =
306+
self.inactive_workspace_configs(active_workspaces);
307+
308+
inactive_configs
309+
.iter()
310+
.find(|config| config.bind_to_monitor.is_none())
305311
.or(inactive_configs.first())
306312
.cloned()
307313
}

packages/wm/src/windows/commands/move_window_to_workspace.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub fn move_window_to_workspace(
3131
Some(_) => anyhow::Ok(target_workspace),
3232
_ => match target_workspace_name {
3333
Some(name) => {
34-
activate_workspace(Some(&name), &current_monitor, state, config)?;
34+
activate_workspace(Some(&name), None, state, config)?;
3535

3636
Ok(state.workspace_by_name(&name))
3737
}
@@ -124,17 +124,18 @@ pub fn move_window_to_workspace(
124124
state.pending_sync.focus_change = true;
125125
}
126126

127-
match window {
128-
WindowContainer::NonTilingWindow(_) => {
129-
state.pending_sync.containers_to_redraw.push(window.into());
130-
}
131-
WindowContainer::TilingWindow(_) => {
132-
state
133-
.pending_sync
134-
.containers_to_redraw
135-
.extend(current_workspace.tiling_children().map(Into::into));
136-
}
137-
}
127+
let containers_to_redraw = match window {
128+
WindowContainer::NonTilingWindow(_) => vec![window.into()],
129+
WindowContainer::TilingWindow(_) => current_workspace
130+
.tiling_children()
131+
.map(Into::into)
132+
.collect(),
133+
};
134+
135+
state
136+
.pending_sync
137+
.containers_to_redraw
138+
.extend(containers_to_redraw);
138139
}
139140

140141
Ok(())

packages/wm/src/workspaces/commands/activate_workspace.rs

+57-24
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use anyhow::Context;
33
use super::sort_workspaces;
44
use crate::{
55
common::TilingDirection,
6-
containers::{commands::attach_container, traits::PositionGetters},
6+
containers::{
7+
commands::attach_container,
8+
traits::{CommonGetters, PositionGetters},
9+
},
710
monitors::Monitor,
811
user_config::{UserConfig, WorkspaceConfig},
912
wm_event::WmEvent,
@@ -15,14 +18,39 @@ use crate::{
1518
///
1619
/// If no workspace name is provided, the first suitable workspace defined
1720
/// in the user's config will be used.
21+
///
22+
/// If no target monitor is provided, the workspace is activated on
23+
/// whichever monitor it is bound to, or the currently focused monitor.
1824
pub fn activate_workspace(
1925
workspace_name: Option<&str>,
20-
target_monitor: &Monitor,
26+
target_monitor: Option<Monitor>,
2127
state: &mut WmState,
2228
config: &UserConfig,
2329
) -> anyhow::Result<()> {
24-
let workspace_config =
25-
workspace_config(workspace_name, target_monitor, state, config)?;
30+
let workspace_config = workspace_config(
31+
workspace_name,
32+
target_monitor.clone(),
33+
state,
34+
config,
35+
)?;
36+
37+
let target_monitor = target_monitor
38+
.or_else(|| {
39+
workspace_config
40+
.bind_to_monitor
41+
.and_then(|index| {
42+
state
43+
.monitors()
44+
.into_iter()
45+
.find(|monitor| monitor.index() == index as usize)
46+
})
47+
.or_else(|| {
48+
state
49+
.focused_container()
50+
.and_then(|focused| focused.monitor())
51+
})
52+
})
53+
.context("Failed to get a target monitor for the workspace.")?;
2654

2755
let monitor_rect = target_monitor.to_rect()?;
2856
let tiling_direction = match monitor_rect.height() > monitor_rect.width()
@@ -56,28 +84,33 @@ pub fn activate_workspace(
5684
/// Gets config for the workspace to activate.
5785
fn workspace_config(
5886
workspace_name: Option<&str>,
59-
target_monitor: &Monitor,
87+
target_monitor: Option<Monitor>,
6088
state: &mut WmState,
6189
config: &UserConfig,
6290
) -> anyhow::Result<WorkspaceConfig> {
63-
match workspace_name {
64-
Some(workspace_name) => {
65-
let found_config = config
66-
.inactive_workspace_configs(&state.workspaces())
67-
.into_iter()
68-
.find(|config| config.name == workspace_name)
69-
.with_context(|| {
70-
format!("Workspace with name {} doesn't exist.", workspace_name)
71-
})?;
72-
73-
Ok(found_config.clone())
74-
}
75-
None => {
76-
let inactive_config = config
77-
.workspace_config_for_monitor(&target_monitor, &state.workspaces())
78-
.context("No workspace config found for monitor.")?;
91+
let found_config = match workspace_name {
92+
Some(workspace_name) => config
93+
.inactive_workspace_configs(&state.workspaces())
94+
.into_iter()
95+
.find(|config| config.name == workspace_name)
96+
.with_context(|| {
97+
format!(
98+
"Workspace with name '{}' doesn't exist or is already active.",
99+
workspace_name
100+
)
101+
}),
102+
None => target_monitor
103+
.and_then(|target_monitor| {
104+
config.workspace_config_for_monitor(
105+
&target_monitor,
106+
&state.workspaces(),
107+
)
108+
})
109+
.or_else(|| {
110+
config.next_inactive_workspace_config(&state.workspaces())
111+
})
112+
.context("No workspace config available to activate workspace."),
113+
};
79114

80-
Ok(inactive_config.clone())
81-
}
82-
}
115+
found_config.cloned()
83116
}

packages/wm/src/workspaces/commands/focus_workspace.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@ pub fn focus_workspace(
3535
Some(_) => anyhow::Ok(target_workspace),
3636
_ => match target_workspace_name {
3737
Some(name) => {
38-
let focused_monitor =
39-
focused_workspace.monitor().context("No focused monitor.")?;
40-
41-
activate_workspace(Some(&name), &focused_monitor, state, config)?;
38+
activate_workspace(Some(&name), None, state, config)?;
4239

4340
Ok(state.workspace_by_name(&name))
4441
}

packages/wm/src/workspaces/commands/move_workspace_in_direction.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub fn move_workspace_in_direction(
5757

5858
// Prevent original monitor from having no workspaces.
5959
if monitor.child_count() == 0 {
60-
activate_workspace(None, &monitor, state, config)?;
60+
activate_workspace(None, Some(monitor), state, config)?;
6161
}
6262

6363
sort_workspaces(target_monitor, config)?;

0 commit comments

Comments
 (0)