Compare commits

..

4 Commits

Author SHA1 Message Date
dependabot[bot] ccb39abd2e chore(deps): bump starship-battery from 0.10.3 to 0.11.0
Bumps [starship-battery](https://github.com/starship/rust-battery) from 0.10.3 to 0.11.0.
- [Release notes](https://github.com/starship/rust-battery/releases)
- [Changelog](https://github.com/starship/rust-battery/blob/main/CHANGELOG.md)
- [Commits](https://github.com/starship/rust-battery/compare/v0.10.3...v0.11.0)

---
updated-dependencies:
- dependency-name: starship-battery
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 16:12:27 -07:00
dependabot[bot] f22fb8086c chore(deps): bump nanoid from 0.4.0 to 0.5.0
Bumps [nanoid](https://github.com/mrdimidium/nanoid) from 0.4.0 to 0.5.0.
- [Changelog](https://github.com/mrdimidium/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/mrdimidium/nanoid/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-version: 0.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-25 16:11:37 -07:00
LGUG2Z 538053c9c8 chore(deps): cargo update 2026-06-24 14:58:47 -07:00
ChinhLee 57b93a7404 fix(wm): verify foreground state before mutating focus state
As a defense-in-depth fix independent of the event-conversion layer, the
WindowManagerEvent::FocusChange handler should not update the focused
monitor/workspace/container/window state when the incoming window is not
the actual OS foreground window.

The issue notes that after a monitor switch komorebi focuses "the last
window focused from monitor 1" while the popout window on the other
monitor still receives input.

This is exactly the symptom of komorebi processing a stale/background
focus event and re-pointing its selection at monitor 1 even though real
focus is elsewhere. Verifying foreground state before mutating focus
state prevents the desync regardless of which win-event produced the
FocusChange.

fix #1679

Signed-off-by: ChinhLee <76194645+chinhkrb113@users.noreply.github.com>
2026-06-24 14:55:43 -07:00
5 changed files with 393 additions and 505 deletions
+5 -5
View File
@@ -21,7 +21,7 @@ jobs:
cargo-deny: cargo-deny:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: EmbarkStudios/cargo-deny-action@v2 - uses: EmbarkStudios/cargo-deny-action@v2
@@ -43,7 +43,7 @@ jobs:
RUSTFLAGS: -Ctarget-feature=+crt-static -Dwarnings RUSTFLAGS: -Ctarget-feature=+crt-static -Dwarnings
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- run: rustup toolchain install stable --profile minimal - run: rustup toolchain install stable --profile minimal
@@ -82,7 +82,7 @@ jobs:
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- shell: bash - shell: bash
@@ -129,7 +129,7 @@ jobs:
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- shell: bash - shell: bash
@@ -171,7 +171,7 @@ jobs:
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- shell: bash - shell: bash
Generated
+355 -498
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -34,7 +34,7 @@ reqwest = { version = "0.12", features = ["blocking"] }
schemars = { workspace = true, optional = true } schemars = { workspace = true, optional = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
starship-battery = "0.10" starship-battery = "0.11"
sysinfo = { workspace = true } sysinfo = { workspace = true }
systray-util = "0.2.0" systray-util = "0.2.0"
tokio = { version = "1", features = ["rt", "sync", "time"] } tokio = { version = "1", features = ["rt", "sync", "time"] }
+1 -1
View File
@@ -24,7 +24,7 @@ ed25519-dalek = "2"
hotwatch = { workspace = true } hotwatch = { workspace = true }
lazy_static = { workspace = true } lazy_static = { workspace = true }
miow = "0.6" miow = "0.6"
nanoid = "0.4" nanoid = "0.5"
net2 = "0.2" net2 = "0.2"
os_info = "3.10" os_info = "3.10"
parking_lot = { workspace = true } parking_lot = { workspace = true }
+31
View File
@@ -41,6 +41,30 @@ use crate::windows_api::WindowsApi;
use crate::winevent::WinEvent; use crate::winevent::WinEvent;
use crate::workspace::WorkspaceLayer; use crate::workspace::WorkspaceLayer;
fn should_skip_focus_change(foreground_hwnd: Option<isize>, window_hwnd: isize) -> bool {
matches!(foreground_hwnd, Some(hwnd) if hwnd != window_hwnd)
}
#[cfg(test)]
mod focus_change_tests {
use super::should_skip_focus_change;
#[test]
fn skips_focus_change_from_background_window() {
assert!(should_skip_focus_change(Some(1), 2));
}
#[test]
fn allows_focus_change_for_foreground_window() {
assert!(!should_skip_focus_change(Some(1), 1));
}
#[test]
fn allows_focus_change_when_foreground_unknown() {
assert!(!should_skip_focus_change(None, 1));
}
}
#[tracing::instrument] #[tracing::instrument]
pub fn listen_for_events(wm: Arc<Mutex<WindowManager>>) { pub fn listen_for_events(wm: Arc<Mutex<WindowManager>>) {
let receiver = wm.lock().incoming_events.clone(); let receiver = wm.lock().incoming_events.clone();
@@ -341,6 +365,13 @@ impl WindowManager {
already_moved_window_handles.remove(&window.hwnd); already_moved_window_handles.remove(&window.hwnd);
} }
WindowManagerEvent::FocusChange(_, window) => { WindowManagerEvent::FocusChange(_, window) => {
if should_skip_focus_change(WindowsApi::foreground_window().ok(), window.hwnd) {
tracing::debug!(
"ignoring stale focus change for hwnd {} as it is not the foreground window",
window.hwnd
);
return Ok(());
}
// don't want to trigger the full workspace updates when there are no managed // don't want to trigger the full workspace updates when there are no managed
// containers - this makes floating windows on empty workspaces go into very // containers - this makes floating windows on empty workspaces go into very
// annoying focus change loops which prevents users from interacting with them // annoying focus change loops which prevents users from interacting with them