fix: alt-tab focus history MRU ordering, repeat handling, and quick release

This commit is contained in:
2026-09-09 12:39:10 +02:00
parent 50caed0110
commit 53cebf14f3
5 changed files with 131 additions and 91 deletions
+68 -26
View File
@@ -119,22 +119,79 @@ impl Order {
}
}
fn history_path() -> PathBuf {
std::env::var_os("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.unwrap_or_else(std::env::temp_dir)
.join("wl-pick-history")
}
pub fn record_focus(con_id: i64) {
let path = history_path();
let mut ids: Vec<i64> = std::fs::read_to_string(&path)
.ok()
.map(|s| {
s.lines()
.filter_map(|l| l.trim().parse::<i64>().ok())
.collect()
})
.unwrap_or_default();
ids.retain(|&id| id != con_id);
ids.insert(0, con_id);
ids.truncate(50);
let content = ids
.iter()
.map(|id| id.to_string())
.collect::<Vec<_>>()
.join("\n");
let _ = std::fs::write(&path, content);
}
pub fn read_focus_history() -> Vec<i64> {
std::fs::read_to_string(history_path())
.ok()
.map(|s| {
s.lines()
.filter_map(|l| l.trim().parse::<i64>().ok())
.collect()
})
.unwrap_or_default()
}
/// Views in the tree, either in MRU focus order or tree layout order.
pub fn windows(conn: &mut Connection, order: Order) -> Result<Vec<Target>, swayipc::Error> {
let mut out = Vec::new();
let tree = conn.get_tree()?;
match order {
Order::Mru => {
collect_mru(&tree, &mut out);
// Ensure the currently focused window is at index 0
if let Some(pos) = out.iter().position(|t| t.focused) {
if pos > 0 {
let focused = out.remove(pos);
out.insert(0, focused);
collect_tree(&tree, &mut out);
if out.is_empty() {
return Ok(out);
}
// Record currently focused window into history
if let Some(pos) = out.iter().position(|t| t.focused) {
if let Some(con_id) = out[pos].con_id {
record_focus(con_id);
}
}
if order == Order::Mru {
let history = read_focus_history();
out.sort_by_key(|t| {
if t.focused {
return (0, 0, 0);
}
if let Some(con_id) = t.con_id {
if let Some(idx) = history.iter().position(|&id| id == con_id) {
return (1, idx, 0);
}
}
}
Order::Tree => collect_tree(&tree, &mut out),
if t.visible {
(2, 0, 0)
} else {
(3, 0, 0)
}
});
}
Ok(out)
}
@@ -152,6 +209,7 @@ fn collect_target(node: &Node) -> Option<Target> {
node.app_id.clone().or(class).unwrap_or_default(),
node.name.clone().unwrap_or_default(),
node.focused,
node.visible.unwrap_or(true),
))
} else {
None
@@ -167,22 +225,6 @@ fn collect_tree(node: &Node, out: &mut Vec<Target>) {
}
}
fn collect_mru(node: &Node, out: &mut Vec<Target>) {
if let Some(target) = collect_target(node) {
out.push(target);
}
let mut children: Vec<&Node> = node.nodes.iter().chain(node.floating_nodes.iter()).collect();
children.sort_by_key(|child| {
node.focus
.iter()
.position(|&id| id == child.id)
.unwrap_or(usize::MAX)
});
for child in children {
collect_mru(child, out);
}
}
/// One active display: what the overlay needs to size itself against.
///
/// The overlay maps on the focused display, so percentages and the buffer scale