Skip to content

Commit f2b3784

Browse files
committed
v1.3.8
fix: stop focus steal by ignoring tray location events from our own icon updates
1 parent ae9be67 commit f2b3784

3 files changed

Lines changed: 36 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "claude-code-usage-monitor"
3-
version = "1.3.7"
3+
version = "1.3.8"
44
edition = "2021"
55
license = "MIT"
66
description = "Claude Code Usage Monitor"

src/window.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::PathBuf;
22
use std::sync::atomic::{AtomicU32, Ordering};
33
use std::sync::{Mutex, MutexGuard};
4-
use std::time::{Duration, SystemTime, UNIX_EPOCH};
4+
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
55

66
use serde::{Deserialize, Serialize};
77
use windows::core::PCWSTR;
@@ -118,6 +118,9 @@ const DIVIDER_HIT_ZONE: i32 = 13; // LEFT_DIVIDER_W + DIVIDER_RIGHT_MARGIN
118118

119119
const WM_DPICHANGED_MSG: u32 = 0x02E0;
120120
const WM_APP_UPDATE_CHECK_COMPLETE: u32 = WM_APP + 2;
121+
const TRAY_ICON_UPDATE_REPOSITION_SUPPRESS_MS: u64 = 750;
122+
123+
static SUPPRESS_TRAY_REPOSITION_UNTIL: Mutex<Option<Instant>> = Mutex::new(None);
121124

122125
/// Current system DPI (96 = 100% scaling, 144 = 150%, 192 = 200%, etc.)
123126
static CURRENT_DPI: AtomicU32 = AtomicU32::new(96);
@@ -1448,6 +1451,29 @@ fn update_display() {
14481451
refresh_usage_texts(s);
14491452
}
14501453

1454+
fn suppress_tray_reposition_for(duration: Duration) {
1455+
let mut until = SUPPRESS_TRAY_REPOSITION_UNTIL
1456+
.lock()
1457+
.unwrap_or_else(|e| e.into_inner());
1458+
*until = Some(Instant::now() + duration);
1459+
}
1460+
1461+
fn tray_reposition_is_suppressed() -> bool {
1462+
let now = Instant::now();
1463+
let mut until = SUPPRESS_TRAY_REPOSITION_UNTIL
1464+
.lock()
1465+
.unwrap_or_else(|e| e.into_inner());
1466+
1467+
match *until {
1468+
Some(deadline) if now < deadline => true,
1469+
Some(_) => {
1470+
*until = None;
1471+
false
1472+
}
1473+
None => false,
1474+
}
1475+
}
1476+
14511477
fn position_at_taskbar() {
14521478
refresh_dpi();
14531479
// Drop the app-state lock before any Win32 call that may synchronously
@@ -1543,6 +1569,10 @@ unsafe extern "system" fn on_tray_location_changed(
15431569
};
15441570

15451571
if is_tray {
1572+
if tray_reposition_is_suppressed() {
1573+
return;
1574+
}
1575+
15461576
let should_reposition = {
15471577
let mut last = LAST_REPOSITION.lock().unwrap_or_else(|e| e.into_inner());
15481578
let now = std::time::Instant::now();
@@ -1681,6 +1711,9 @@ unsafe extern "system" fn wnd_proc(
16811711
render_layered();
16821712
schedule_countdown_timer();
16831713
let (pct, tooltip) = tray_icon_data_from_state();
1714+
suppress_tray_reposition_for(Duration::from_millis(
1715+
TRAY_ICON_UPDATE_REPOSITION_SUPPRESS_MS,
1716+
));
16841717
tray_icon::update(hwnd, pct, &tooltip);
16851718
LRESULT(0)
16861719
}

0 commit comments

Comments
 (0)