# Focus Theft on Windows — Diagnostic Reference

## What "focus theft" looks like

The user is working in one app (browser, spreadsheet, etc.). Suddenly a different window — usually Windows Terminal or a console — pops to the foreground for a fraction of a second, briefly stealing keyboard focus, then disappears. The user describes this as "flashing" or "the terminal flashes."

**This is NOT the same as:**
- **Render flicker** — the window content flickers but the window stays in place. Cause: GPU/acrylic repaint. Fix: `useAcrylic: false`.
- **Bell flash** — the window border or taskbar flashes. Cause: escape sequence bell (`\a`). Fix: `bellStyle: "none"`.
- **A window that stays open** — that's a dialog or popup, not focus theft.

Focus theft = a window briefly grabs foreground, then releases it. The user can't type for a moment.

## How to diagnose

### Step 1: Confirm it's focus theft (not render flicker or bell)

Ask the user: "When it flashes, does a window pop to the front briefly and then disappear? Or does the window you're in flicker without moving?" 

If the window pops to the front and disappears → focus theft. Continue below.
If the window stays put but flickers → render/bell issue. Use `bellStyle: "none"` + `useAcrylic: false`.

### Step 2: Run the focus theft monitor

Use `scripts/focus-theft-monitor.ps1` from this skill. It watches at 100ms intervals:
- Every foreground window change (which process, which window title)
- Every new process spawn (with full executable path)

Run it for 5-15 minutes while the user works normally. When the flash happens, the user notes the time. Match the timestamp to the log entries.

**Background mode** (15 min, hidden window):
```powershell
powershell -File scripts\focus-theft-monitor.ps1 -DurationMinutes 15 -Background $true
```

**Foreground mode** (5 min, visible output):
```powershell
powershell -File scripts\focus-theft-monitor.ps1 -DurationMinutes 5
```

### Step 3: Identify the culprit from the log

Look for a `FOCUS_CHANGE` entry at the timestamp the user reported. The `name=` and `title=` fields tell you which process stole focus.

If no `FOCUS_CHANGE` appears at that timestamp, the focus theft may be too fast for 100ms polling. Look for `NEW_PROCESS` entries around that time — a process that spawns with a visible console window (e.g., `conhost.exe`, an `.exe` with no `--type=renderer` flag) can briefly flash a window that's too fast for the poll but still steals focus.

### Step 4: Remove the culprit

Common culprits and their removal:

| Culprit | Symptom | Removal |
|---------|---------|---------|
| **McAfee WebAdvisor** | "Stay protected with McAfee" promo popup | Uninstall via registry-based PowerShell uninstall (see session 20260717) |
| **HP Support Assistant** | "HP Update Notice" window | Uninstall or disable scheduled task |
| **WildTangent Games** | Updater popup | Uninstall via control panel |
| **Google Update** | Brief console window from `updater.exe` | Disable scheduled task `GoogleUpdateTask*` |
| **ExpressVPN** | Notification service popup | Disable startup or uninstall if unused |
| **Windows Search** | `SearchProtocolHost.exe` / `SearchFilterHost.exe` | Normal Windows behavior, not focus theft (these don't grab foreground) |

## Key lessons from sessions

### Session 20260716 (misdiagnosis)
- User reported "terminal flashes every 30 seconds"
- Agent assumed bell/acrylic render issue → wasted time editing `bellStyle`/`useAcrylic` in Windows Terminal settings
- Actual cause: focus theft from background processes
- **Lesson: always ask what the flash LOOKS LIKE before assuming the cause**

### Session 20260717 (correct diagnosis)
- User described: "Terminal appears, can't type for a milisecond, disappears"
- This is focus theft, not render flicker
- McAfee WebAdvisor "Stay protected with McAfee" popup confirmed as one culprit
- Uninstalled McAfee WebAdvisor; Windows Defender auto-activated as sole AV
- Flash persisted intermittently → other bloatware may also contribute
- **Lesson: there can be multiple focus thieves. Removing one may not fully solve it.**

## PowerShell Win32 API pattern for focus monitoring

The monitor uses three Win32 calls via P/Invoke:
- `GetForegroundWindow()` — returns HWND of the current foreground window
- `GetWindowText(hWnd, sb, count)` — gets the window title
- `GetWindowThreadProcessId(hWnd, out pid)` — gets the PID that owns the window

Combined with `Get-CimInstance Win32_Process` for new process detection (provides `ExecutablePath` and `CommandLine` that `Get-Process` doesn't expose without admin).

Poll at 100ms for best catch rate. 200ms may miss fast flashes. 50ms is overkill and CPU-heavy.
