focus workspace on its last monitor instead of moving it to current
- SHA
6c08b3a4be58c0c5132430f428029d690e4d1d44- Parents
-
3ab345f - Tree
b6cf40d
6c08b3a
6c08b3a4be58c0c5132430f428029d690e4d1d443ab345f
b6cf40d| Status | File | + | - |
|---|---|---|---|
| M |
gar/src/core/mod.rs
|
7 | 1 |
| M |
gar/src/core/workspace.rs
|
3 | 0 |
| M |
gar/src/x11/events.rs
|
12 | 6 |
gar/src/core/mod.rsmodified@@ -59,7 +59,7 @@ pub struct WindowManager { | ||
| 59 | 59 | |
| 60 | 60 | impl WindowManager { |
| 61 | 61 | pub fn new(conn: Connection) -> Result<Self> { |
| 62 | - let workspaces: Vec<Workspace> = (1..=10) | |
| 62 | + let mut workspaces: Vec<Workspace> = (1..=10) | |
| 63 | 63 | .map(|i| Workspace::new(i, i.to_string())) |
| 64 | 64 | .collect(); |
| 65 | 65 | |
@@ -131,6 +131,9 @@ impl WindowManager { | ||
| 131 | 131 | for (i, monitor) in monitors.iter_mut().enumerate() { |
| 132 | 132 | monitor.workspaces = vec![i]; // Just track initial workspace |
| 133 | 133 | monitor.active_workspace = i; // Monitor 0 shows ws 0, monitor 1 shows ws 1, etc. |
| 134 | + if i < workspaces.len() { | |
| 135 | + workspaces[i].last_monitor = Some(i); | |
| 136 | + } | |
| 134 | 137 | tracing::debug!("Monitor '{}' starts with workspace {}", monitor.name, i + 1); |
| 135 | 138 | } |
| 136 | 139 | |
@@ -331,6 +334,9 @@ impl WindowManager { | ||
| 331 | 334 | monitor.workspaces = vec![first_free]; |
| 332 | 335 | used_workspaces.insert(first_free); |
| 333 | 336 | } |
| 337 | + if monitor.active_workspace < self.workspaces.len() { | |
| 338 | + self.workspaces[monitor.active_workspace].last_monitor = Some(i); | |
| 339 | + } | |
| 334 | 340 | tracing::info!("Monitor '{}' showing workspace {}", monitor.name, monitor.active_workspace + 1); |
| 335 | 341 | } |
| 336 | 342 | |
gar/src/core/workspace.rsmodified@@ -11,6 +11,8 @@ pub struct Workspace { | ||
| 11 | 11 | pub floating: Vec<XWindow>, |
| 12 | 12 | pub focused: Option<XWindow>, |
| 13 | 13 | pub visible: bool, |
| 14 | + /// Last monitor this workspace was displayed on (for focus-back behavior) | |
| 15 | + pub last_monitor: Option<usize>, | |
| 14 | 16 | } |
| 15 | 17 | |
| 16 | 18 | impl Workspace { |
@@ -22,6 +24,7 @@ impl Workspace { | ||
| 22 | 24 | floating: Vec::new(), |
| 23 | 25 | focused: None, |
| 24 | 26 | visible: id == 1, |
| 27 | + last_monitor: None, | |
| 25 | 28 | } |
| 26 | 29 | } |
| 27 | 30 | |
gar/src/x11/events.rsmodified@@ -2417,6 +2417,7 @@ impl WindowManager { | ||
| 2417 | 2417 | // Focus the monitor that has this workspace |
| 2418 | 2418 | self.focused_monitor = monitor_idx; |
| 2419 | 2419 | self.focused_workspace = idx; |
| 2420 | + self.workspaces[idx].last_monitor = Some(monitor_idx); | |
| 2420 | 2421 | |
| 2421 | 2422 | // Update EWMH |
| 2422 | 2423 | self.conn.set_current_desktop(idx as u32)?; |
@@ -2441,13 +2442,16 @@ impl WindowManager { | ||
| 2441 | 2442 | self.conn.set_active_window(None)?; |
| 2442 | 2443 | } |
| 2443 | 2444 | } else { |
| 2444 | - // Workspace not visible - show it on current monitor (i3 behavior) | |
| 2445 | - let current_monitor = self.focused_monitor; | |
| 2446 | - let old_ws = self.monitors[current_monitor].active_workspace; | |
| 2445 | + // Workspace not visible — show it on the monitor it was last on, | |
| 2446 | + // falling back to the current monitor if it was never shown. | |
| 2447 | + let target_monitor = self.workspaces[idx].last_monitor | |
| 2448 | + .filter(|&m| m < self.monitors.len()) | |
| 2449 | + .unwrap_or(self.focused_monitor); | |
| 2450 | + let old_ws = self.monitors[target_monitor].active_workspace; | |
| 2447 | 2451 | |
| 2448 | 2452 | tracing::info!( |
| 2449 | 2453 | "Switching monitor {} from workspace {} to {}", |
| 2450 | - current_monitor, old_ws + 1, idx + 1 | |
| 2454 | + target_monitor, old_ws + 1, idx + 1 | |
| 2451 | 2455 | ); |
| 2452 | 2456 | |
| 2453 | 2457 | // Hide windows on old workspace |
@@ -2464,7 +2468,9 @@ impl WindowManager { | ||
| 2464 | 2468 | } |
| 2465 | 2469 | |
| 2466 | 2470 | // Update monitor's active workspace |
| 2467 | - self.monitors[current_monitor].active_workspace = idx; | |
| 2471 | + self.monitors[target_monitor].active_workspace = idx; | |
| 2472 | + self.workspaces[idx].last_monitor = Some(target_monitor); | |
| 2473 | + self.focused_monitor = target_monitor; | |
| 2468 | 2474 | self.focused_workspace = idx; |
| 2469 | 2475 | |
| 2470 | 2476 | // Update EWMH |
@@ -2492,7 +2498,7 @@ impl WindowManager { | ||
| 2492 | 2498 | self.focused_window = None; |
| 2493 | 2499 | self.conn.set_active_window(None)?; |
| 2494 | 2500 | if warp_pointer { |
| 2495 | - let monitor_geom = self.monitors[current_monitor].geometry; | |
| 2501 | + let monitor_geom = self.monitors[target_monitor].geometry; | |
| 2496 | 2502 | let center_x = monitor_geom.x + (monitor_geom.width as i16 / 2); |
| 2497 | 2503 | let center_y = monitor_geom.y + (monitor_geom.height as i16 / 2); |
| 2498 | 2504 | self.conn.warp_pointer(center_x, center_y)?; |