@@ -1219,13 +1219,53 @@ impl WindowManager { |
| 1219 | let screen = self.screen_rect(); | 1219 | let screen = self.screen_rect(); |
| 1220 | let geometries = self.current_workspace().tree.calculate_geometries(screen); | 1220 | let geometries = self.current_workspace().tree.calculate_geometries(screen); |
| 1221 | | 1221 | |
| 1222 | - if let Some(target) = Node::find_adjacent(&geometries, focused, direction) { | 1222 | + // Look up remembered window for this direction (window memory) |
| | 1223 | + let preferred = self.directional_focus_memory.get(&(focused, direction)).copied(); |
| | 1224 | + |
| | 1225 | + if let Some(target) = Node::find_adjacent(&geometries, focused, direction, preferred) { |
| | 1226 | + // Store the directional focus memory for next time |
| | 1227 | + self.directional_focus_memory.insert((focused, direction), target); |
| | 1228 | + |
| | 1229 | + // Store reverse direction only if windows are aligned (same row/column) |
| | 1230 | + // This enables "back" navigation without breaking natural movement |
| | 1231 | + if let (Some((_, from_rect)), Some((_, to_rect))) = ( |
| | 1232 | + geometries.iter().find(|(w, _)| *w == focused), |
| | 1233 | + geometries.iter().find(|(w, _)| *w == target), |
| | 1234 | + ) { |
| | 1235 | + let dominated = match direction { |
| | 1236 | + // For Left/Right: store reverse if windows share vertical space (same row) |
| | 1237 | + Direction::Left | Direction::Right => { |
| | 1238 | + let overlap_start = from_rect.y.max(to_rect.y); |
| | 1239 | + let overlap_end = (from_rect.y + from_rect.height as i16) |
| | 1240 | + .min(to_rect.y + to_rect.height as i16); |
| | 1241 | + overlap_start < overlap_end |
| | 1242 | + } |
| | 1243 | + // For Up/Down: store reverse if windows share horizontal space (same column) |
| | 1244 | + Direction::Up | Direction::Down => { |
| | 1245 | + let overlap_start = from_rect.x.max(to_rect.x); |
| | 1246 | + let overlap_end = (from_rect.x + from_rect.width as i16) |
| | 1247 | + .min(to_rect.x + to_rect.width as i16); |
| | 1248 | + overlap_start < overlap_end |
| | 1249 | + } |
| | 1250 | + }; |
| | 1251 | + |
| | 1252 | + if dominated { |
| | 1253 | + let opposite = match direction { |
| | 1254 | + Direction::Left => Direction::Right, |
| | 1255 | + Direction::Right => Direction::Left, |
| | 1256 | + Direction::Up => Direction::Down, |
| | 1257 | + Direction::Down => Direction::Up, |
| | 1258 | + }; |
| | 1259 | + self.directional_focus_memory.insert((target, opposite), focused); |
| | 1260 | + } |
| | 1261 | + } |
| | 1262 | + |
| 1223 | // Focus new window (keyboard navigation, warp pointer) | 1263 | // Focus new window (keyboard navigation, warp pointer) |
| 1224 | // set_focus handles grab/ungrab for old and new windows | 1264 | // set_focus handles grab/ungrab for old and new windows |
| 1225 | self.set_focus(target, true)?; | 1265 | self.set_focus(target, true)?; |
| 1226 | self.conn.flush()?; | 1266 | self.conn.flush()?; |
| 1227 | | 1267 | |
| 1228 | - tracing::debug!("Focused {:?} to window {}", direction, target); | 1268 | + tracing::debug!("Focused {:?} to window {} (preferred: {:?})", direction, target, preferred); |
| 1229 | } else { | 1269 | } else { |
| 1230 | // No adjacent window on this workspace - try adjacent monitor | 1270 | // No adjacent window on this workspace - try adjacent monitor |
| 1231 | self.focus_adjacent_monitor(direction)?; | 1271 | self.focus_adjacent_monitor(direction)?; |
@@ -1293,7 +1333,7 @@ impl WindowManager { |
| 1293 | let screen = self.screen_rect(); | 1333 | let screen = self.screen_rect(); |
| 1294 | let geometries = self.current_workspace().tree.calculate_geometries(screen); | 1334 | let geometries = self.current_workspace().tree.calculate_geometries(screen); |
| 1295 | | 1335 | |
| 1296 | - if let Some(target) = Node::find_adjacent(&geometries, focused, direction) { | 1336 | + if let Some(target) = Node::find_adjacent(&geometries, focused, direction, None) { |
| 1297 | // Swap the windows in the tree | 1337 | // Swap the windows in the tree |
| 1298 | self.current_workspace_mut().tree.swap(focused, target); | 1338 | self.current_workspace_mut().tree.swap(focused, target); |
| 1299 | | 1339 | |