cloud storage client
git clone https://git.lucas.co/cce-cloud.git
Commit the window switcher on Alt release as well as Super
The switcher assumed Super opened it and committed on the first
modifiers event with Super up, so an alt+tab binding committed at once,
with Alt still down. It now counts as held while Super or Alt is down
and commits once neither is, so either chord can be bound to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLAUDE.md | 2 +-
src/main.rs | 23 ++++++++++++++---------
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index 49f3999..30f9124 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -86,7 +86,7 @@ needs-stdin decision, in `run_client()`).
- `Dmenu` — items from stdin, selection echoed out. Magic stdin lines
`__cce_switcher_next__` / `__cce_switcher_select_and_close__` drive the compositor's
- window switcher (`--switcher` starts in Dmenu with Super held).
+ window switcher (`--switcher` starts in Dmenu with its hold modifier down, and commits when neither Super nor Alt is held, so it works bound to Super+Tab or Alt+Tab).
- `Path` — executables scanned from `$PATH`.
**Key repeat** is the client's job on Wayland: the keyboard is bound with
`get_keyboard_with_repeat` on the calloop loop, which re-fires a held key at
diff --git a/src/main.rs b/src/main.rs
index 46d0ea3..037ed56 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2440,7 +2440,10 @@ struct AppState {
exit: bool,
redraw: bool,
ctrl_pressed: bool,
- super_pressed: bool,
+ /// The switcher's hold modifier — Super or Alt, whichever chord opened
+ /// it — is still down. Starts true in switcher mode (the chord that
+ /// opened it is held); its release commits the highlighted row.
+ switch_held: bool,
switcher_mode: bool,
/// When the compositor's close dissolve ends and this popup may go, set
/// by `trigger_close`. `None` while the popup is live. The surface has to
@@ -3047,13 +3050,15 @@ impl KeyboardHandler for AppState {
modifiers: smithay_client_toolkit::seat::keyboard::Modifiers,
_layout: u32,
) {
- let prev_super = self.super_pressed;
+ let prev_held = self.switch_held;
self.ctrl_pressed = modifiers.ctrl;
- self.super_pressed = modifiers.logo;
- log::debug!("update_modifiers: logo={}, prev_logo={}", modifiers.logo, prev_super);
+ // Super+Tab or Alt+Tab: either can be bound to the switcher, and it
+ // cannot tell which opened it, so it commits once neither is held.
+ self.switch_held = modifiers.logo || modifiers.alt;
+ log::debug!("update_modifiers: logo={}, alt={}, prev_held={}", modifiers.logo, modifiers.alt, prev_held);
- if self.switcher_mode && prev_super && !self.super_pressed {
- log::info!("Super modifier released in switcher mode, selecting currently highlighted item");
+ if self.switcher_mode && prev_held && !self.switch_held {
+ log::info!("Switcher modifier (Super/Alt) released, selecting currently highlighted item");
self.trigger_select_and_close();
}
}
@@ -3542,7 +3547,7 @@ fn run_standalone() {
exit: false,
redraw: false,
ctrl_pressed: false,
- super_pressed: switcher_mode,
+ switch_held: switcher_mode,
switcher_mode,
fade_until: None,
cce_toplevel: None,
@@ -3856,7 +3861,7 @@ fn run_daemon(socket_path: &str) {
exit: false,
redraw: false,
ctrl_pressed: false,
- super_pressed: false,
+ switch_held: false,
switcher_mode: false,
fade_until: None,
cce_toplevel: None,
@@ -4130,7 +4135,7 @@ fn run_daemon(socket_path: &str) {
}
}).unwrap();
- app.super_pressed = switcher_mode;
+ app.switch_held = switcher_mode;
app.switcher_mode = switcher_mode;
app.selected_item = None;