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
+18 -37
View File
@@ -24,7 +24,6 @@ use wayland_protocols_wlr::layer_shell::v1::client::{
use wayland_protocols::wp::cursor_shape::v1::client::wp_cursor_shape_device_v1::Shape;
use crate::app::{App, Ending};
use crate::config::AltTabMode;
use crate::shm;
use crate::theme::{Rect, fit_centred};
@@ -338,7 +337,7 @@ impl App {
}
fn key(&mut self, code: u32, qh: &QueueHandle<Self>) {
if self.is_alt_tab && is_trigger_modifier(code) {
if is_trigger_modifier(code) {
self.latched_modifiers.insert(code);
}
// Arm client-side repeat for navigation keys.
@@ -380,10 +379,7 @@ impl App {
self.repeat_key = None;
self.repeat_next = None;
}
if self.is_alt_tab
&& self.latched_modifiers.remove(&code)
&& self.latched_modifiers.is_empty()
{
if self.latched_modifiers.remove(&code) && self.latched_modifiers.is_empty() {
if self.ending == Ending::Running {
self.picked = self.tiles.get(self.sel).map(|t| t.target.clone());
self.ending = Ending::Picked;
@@ -412,7 +408,7 @@ impl App {
}
}
fn keyboard_enter(&mut self, keys: Vec<u8>, qh: &QueueHandle<Self>) {
fn keyboard_enter(&mut self, keys: Vec<u8>, _qh: &QueueHandle<Self>) {
self.focused = true;
let held_keys: Vec<u32> = keys
.chunks_exact(4)
@@ -429,41 +425,26 @@ impl App {
.filter(|&k| is_trigger_modifier(k))
.collect();
if !held_modifiers.is_empty() && self.alt_tab != AltTabMode::No {
self.is_alt_tab = true;
for &m in &held_modifiers {
self.latched_modifiers.insert(m);
}
for &m in &held_modifiers {
self.latched_modifiers.insert(m);
}
if self.is_alt_tab && !self.initial_stepped {
self.initial_stepped = true;
if self.alt_tab == AltTabMode::Auto {
if self.latched_modifiers.is_empty() {
// Auto mode: no modifier held on enter means the mod was
// released before focus arrived — commit immediately.
if self.ending == Ending::Running {
self.picked = self.tiles.get(self.sel).map(|t| t.target.clone());
self.ending = Ending::Picked;
}
} else {
// Modifier is held: step selection now.
let step = if self.shift { -1 } else { 1 };
self.move_sel(step, qh);
}
}
}
// For both Yes and Auto: if we are in alt-tab mode but no modifier is
// currently held, the mod was released before keyboard focus arrived.
// Commit the current selection immediately.
if self.is_alt_tab && self.latched_modifiers.is_empty() && self.ending == Ending::Running {
if self.alt_tab == AltTabMode::Yes
|| (self.alt_tab == AltTabMode::Auto && self.initial_stepped)
{
// If no modifier is held on enter, the modifier (and/or Tab) was
// released before focus was acquired: commit selection immediately!
if self.latched_modifiers.is_empty() {
if self.ending == Ending::Running {
self.picked = self.tiles.get(self.sel).map(|t| t.target.clone());
self.ending = Ending::Picked;
}
return;
}
// A modifier is held. If Tab is also held upon enter, arm key-repeat
// immediately so holding Tab cycles through windows.
if held_keys.iter().any(|&k| k == KEY_TAB) {
let delay = std::time::Duration::from_millis(self.repeat_delay_ms as u64);
self.repeat_key = Some(KEY_TAB);
self.repeat_next = Some(std::time::Instant::now() + delay);
}
}
}