Unexpected Alt+Tab behavior

Hi everyone,

I have been plagued by a specific Alt+Tab behavior for a long time: occasionally, when cycling between two windows (A and B), pressing Alt+Tab unexpectedly switches to a third window (C) instead of the previous one.

This issue breaks muscle memory and is incredibly disruptive to the user experience. I found an existing discussion about this here:
Alt-tab intermittently switches to the wrong window, but the root cause remained elusive.

I decided to dig into the KWin source code, apply some instrumentation, and debug the issue. I believe I have found the mechanism causing this (might not be the only one though). I’m posting this here instead of https://bugs.kde.org because I’m not sure if this is a bug.

The Root Cause

The issue arises from an interaction between Window Rules (specifically those matching titles) and the Focus Chain.

Prerequisites:

  1. You have at least 3 windows open (A, B, C).
  2. There is a Window Rule configured that matches Window B’s class/type/role (unimportant match is considered a match as well), AND this rule includes a non-trivial Title property match (e.g., Exact Match, Substring Match, etc.).
    • Note: The rule doesn’t need to have certain settings; the key is that KWin is monitoring the title for rule evaluation.

Reproduction Steps:

  1. Focus Window A, then Focus Window B.
  2. Switch back to Window A (B is now the “previous” window).
  3. The Trigger: While Window B is in the background, its title changes.
    • Example: Window B is a terminal. You run sleep 2 and switch to Window A. When the command finishes, the terminal updates its title.
  4. Press Alt+Tab.
  5. Result: KWin switches to Window C (the 3rd window) instead of Window B.

Code Analysis

Here is what happens internally when the background window (B) updates its title:

  1. Because there is a window rule involving title matching, KWin connects the title change signal to Window::evaluateWindowRules (this is done inside Rules::match).
  2. evaluateWindowRules calls Window::applyWindowRules.
  3. Inside applyWindowRules, it calls setOnActivities(activities()).
  4. This triggers updateActivities(false).
  5. Finally, this calls Workspace::self()->focusChain()->update(this, FocusChain::MakeFirst).

The Consequence:
Even though Window B is in the background, the rule re-evaluation silently promotes it to the “First” position in the Focus Chain.

  • Original Chain: A (Active) → B (Last Used) → C
  • After Title Update: B (Moved to First) → A → C
  • Result: Since you are currently on A, the “next” window in the MRU (Most Recently Used) list is now effectively C, because B has been artificially injected before A.

Conclusion & Next Steps

This explains why the bug feels random—it often depends on background processes (like a compiler finishing in a terminal or a browser tab updating) changing a window title while a specific window rule exists.

I am not sure if updateActivities implies a necessity to update the focus chain to MakeFirst during a rule re-evaluation, or if this is an unintended side effect.

I am very willing to contribute a fix for this. However, I would appreciate some guidance from the KWin maintainers: what is the preferred way to handle this? Should we prevent the focus chain update when rules are just being re-evaluated for title changes?

Thanks!

Posting this here because you referenced my original bug report.

I was never able to pin this down on specific circumstances, but now that you mentioned changing window titles, it makes sense. I see the described behaviour most often when I have my web-based time tracker running in an active tab in Firefox. This particular app (Kimai) updates the window/tab title while the timer is running with the current elapsed time, so it’s updated every second. When this tab is active, I get switched back to it instead of the window I was expecting quite frequently, and when I make a different tab active, it doesn’t happen. So it looks like you indeed found the root cause for this behaviour.