Qtile: guard key commands when layout or focused window is unavailable #207

Open
opened 2026-09-14 15:05:24 +00:00 by nsaspy · 0 comments
Owner

Evidence

The supplied log contains runtime key-command failures:

KB command error left: No such command
KB command error kill: No object window in path 'window'

Root cause

The same bindings are active for every group and layout:

Key([mod], "q", lazy.window.kill()),
Key([mod], "Left", lazy.layout.left()),
Key([mod], "Right", lazy.layout.right()),
Key([mod], "h", lazy.layout.left()),
Key([mod], "l", lazy.layout.right()),

However:

  • The first group uses the max layout, which does not expose every directional layout command.
  • lazy.window.kill() resolves through the current window object and errors when the group has no focused window.

Affected files:

  • .config/qtile/qtile.org — source of truth
  • .config/qtile/config.py — tangled output

Documented fix

Use layout-neutral focus commands

Use previous() / next() for the global focus bindings so they work across max, tiled, matrix, ratio, and floating layouts:

Key([mod], "h", lazy.layout.previous()),
Key([mod], "Left", lazy.layout.previous()),
Key([mod], "k", lazy.layout.previous()),
Key([mod], "Up", lazy.layout.previous()),
Key([mod], "j", lazy.layout.next()),
Key([mod], "Down", lazy.layout.next()),
Key([mod], "l", lazy.layout.next()),
Key([mod], "Right", lazy.layout.next()),

If directional semantics must be retained for specific layouts, use conditional lazy commands with .when(layout=[...]) and a previous() / next() fallback instead of calling an unsupported command globally.

Guard window destruction

Replace direct lazy.window.kill() bindings with a guarded helper:

@lazy.function
def kill_focused_window(qtile):
    if qtile.current_window is not None:
        qtile.current_window.kill()
Key([mod], "q", kill_focused_window()),
Key([mod, "shift"], "q", kill_focused_window()),

Apply the changes in qtile.org, then tangle config.py.

Acceptance criteria

  • Focus keys work on the max group without No such command errors.
  • Pressing the kill binding on an empty group is a no-op.
  • Pressing the kill binding with a focused client still closes it.
  • No KB command error left or KB command error kill entries appear in the Qtile log.
## Evidence The supplied log contains runtime key-command failures: ```text KB command error left: No such command KB command error kill: No object window in path 'window' ``` ## Root cause The same bindings are active for every group and layout: ```python Key([mod], "q", lazy.window.kill()), Key([mod], "Left", lazy.layout.left()), Key([mod], "Right", lazy.layout.right()), Key([mod], "h", lazy.layout.left()), Key([mod], "l", lazy.layout.right()), ``` However: - The first group uses the `max` layout, which does not expose every directional layout command. - `lazy.window.kill()` resolves through the current window object and errors when the group has no focused window. Affected files: - `.config/qtile/qtile.org` — source of truth - `.config/qtile/config.py` — tangled output ## Documented fix ### Use layout-neutral focus commands Use `previous()` / `next()` for the global focus bindings so they work across `max`, tiled, matrix, ratio, and floating layouts: ```python Key([mod], "h", lazy.layout.previous()), Key([mod], "Left", lazy.layout.previous()), Key([mod], "k", lazy.layout.previous()), Key([mod], "Up", lazy.layout.previous()), Key([mod], "j", lazy.layout.next()), Key([mod], "Down", lazy.layout.next()), Key([mod], "l", lazy.layout.next()), Key([mod], "Right", lazy.layout.next()), ``` If directional semantics must be retained for specific layouts, use conditional lazy commands with `.when(layout=[...])` and a `previous()` / `next()` fallback instead of calling an unsupported command globally. ### Guard window destruction Replace direct `lazy.window.kill()` bindings with a guarded helper: ```python @lazy.function def kill_focused_window(qtile): if qtile.current_window is not None: qtile.current_window.kill() ``` ```python Key([mod], "q", kill_focused_window()), Key([mod, "shift"], "q", kill_focused_window()), ``` Apply the changes in `qtile.org`, then tangle `config.py`. ## Acceptance criteria - Focus keys work on the `max` group without `No such command` errors. - Pressing the kill binding on an empty group is a no-op. - Pressing the kill binding with a focused client still closes it. - No `KB command error left` or `KB command error kill` entries appear in the Qtile log.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
nsaspy/dotfiles#207
No description provided.