Problem
Reported: with certain options on, EDNexus minimizes other windows and interferes with EDCopilot on a system jump.
Analysis (static; not yet reproduced)
EDNexus contains no code that minimizes any window: nothing sets WindowState, calls ShowWindow/SetForegroundWindow, or sends keys. So any minimizing is an indirect effect of what the app does to the desktop around a jump. On an FSDJump the only parts of EDNexus that touch the desktop are:
1. The in-game overlay (Settings -> Overlay & Voice -> "Show in-game overlay") - prime suspect
It is the only thing that owns a topmost window (OverlayWindow: Topmost="True", transparent, SizeToContent="WidthAndHeight", layered + click-through via Win32 styles in WindowsOverlay). Findings:
- The window resizes on every jump.
MainWindowViewModel.Refresh builds overlay content and posts UpdateContent on every 250 ms tick. A jump changes the system line, shows/hides the "Next jump" line as the route advances, changes the fuel line and rebuilds the colonisation shortfall list. Because the window is SizeToContent, each of those is a native resize of a topmost, layered window sitting over the game. Windows treats topmost z-order and size changes over a borderless/exclusive-fullscreen game as a focus/composition event, which is a plausible way for the game (or another topmost overlay such as EDCopilot's) to lose focus or be minimized.
UpdateContent touches controls every tick even when nothing changed, including assigning a new ItemsSource list each tick while a colonisation shortfall exists, forcing a re-layout every 250 ms.
WS_EX_NOACTIVATE is not set. WindowsOverlay.MakeClickThrough adds WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW only. ShowActivated="False" only affects the initial show; nothing stops the window from being activated later (e.g. by a resize or z-order change), which would steal focus from the game.
- The overlay is topmost over everything, not just the game. There is no foreground-window or "is Elite running/focused" check anywhere in the code, so the overlay sits on top of EDCopilot and every other app all the time (the Settings text says "over the game", but the code does not limit it to the game).
2. Voice callouts (Settings -> "Speak callouts") - can disturb EDCopilot's audio/voice, not windows
VoiceCalloutTracker.OnArrival fires on FSDJump/CarrierJump/Location and speaks the known mining spots callout (enabled by Settings -> Mining -> "Call out known planetary mining spots on arrival", which also needs "Speak callouts" on) through a late-bound SAPI SpVoice on the default audio device. This does not manipulate windows, but it is the one voice callout tied to a jump and can contend with EDCopilot's own speech. Note that this callout has no checkbox in the Voice > Callouts list (Fuel low / Scan complete / Shopping-list item), so it is easy to miss.
3. Not window-related (ruled out)
Discord Rich Presence, the Twitch stream card, EDDN/Inara uploads and the mining chime also react to a jump, but they only use network/IPC/audio; none creates or alters a window.
What to try first (workaround for now)
- Turn "Show in-game overlay" off (Settings -> Overlay & Voice) and jump with EDCopilot running. If the problem stops, it is the overlay.
- If it persists, turn off "Speak callouts" (or just "Call out known planetary mining spots on arrival" under Mining).
- Note the Elite display mode: the overlay is documented for borderless/windowed; exclusive fullscreen is much more sensitive to any topmost window change.
Proposed fix
- Never resize the overlay on a jump: give it a fixed size (or reserve space for the maximum content) so content changes never produce a native resize; only resize when the layout genuinely changes, never per tick.
- Update only what changed: compare the new
OverlayContent with the last one and skip the update when equal; stop reassigning ItemsSource each tick.
- Add
WS_EX_NOACTIVATE (and keep TOOLWINDOW) so the overlay can never take activation, and verify with a test harness that it never becomes the foreground window.
- Show only while Elite Dangerous is running and focused (foreground-window detection behind the existing
IOverlay interface, with a no-op elsewhere), plus a setting to keep the old always-on behaviour; this keeps it from sitting over EDCopilot and other apps.
- Diagnostics: optional trace of overlay show/hide/resize/activation events so a bug report can show exactly what happened on a jump.
- Voice: surface the mining-spot arrival callout in the Voice > Callouts list, and document running alongside EDCopilot; consider an option to choose the audio output.
Acceptance criteria
Related: #184 (position-aware overlay widgets) must not be built on the current always-on-top, self-resizing window.
🤖 Generated with Claude Code
Problem
Reported: with certain options on, EDNexus minimizes other windows and interferes with EDCopilot on a system jump.
Analysis (static; not yet reproduced)
EDNexus contains no code that minimizes any window: nothing sets
WindowState, callsShowWindow/SetForegroundWindow, or sends keys. So any minimizing is an indirect effect of what the app does to the desktop around a jump. On anFSDJumpthe only parts of EDNexus that touch the desktop are:1. The in-game overlay (Settings -> Overlay & Voice -> "Show in-game overlay") - prime suspect
It is the only thing that owns a topmost window (
OverlayWindow:Topmost="True", transparent,SizeToContent="WidthAndHeight", layered + click-through via Win32 styles inWindowsOverlay). Findings:MainWindowViewModel.Refreshbuilds overlay content and postsUpdateContenton every 250 ms tick. A jump changes the system line, shows/hides the "Next jump" line as the route advances, changes the fuel line and rebuilds the colonisation shortfall list. Because the window isSizeToContent, each of those is a native resize of a topmost, layered window sitting over the game. Windows treats topmost z-order and size changes over a borderless/exclusive-fullscreen game as a focus/composition event, which is a plausible way for the game (or another topmost overlay such as EDCopilot's) to lose focus or be minimized.UpdateContenttouches controls every tick even when nothing changed, including assigning a newItemsSourcelist each tick while a colonisation shortfall exists, forcing a re-layout every 250 ms.WS_EX_NOACTIVATEis not set.WindowsOverlay.MakeClickThroughaddsWS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOWonly.ShowActivated="False"only affects the initial show; nothing stops the window from being activated later (e.g. by a resize or z-order change), which would steal focus from the game.2. Voice callouts (Settings -> "Speak callouts") - can disturb EDCopilot's audio/voice, not windows
VoiceCalloutTracker.OnArrivalfires onFSDJump/CarrierJump/Locationand speaks the known mining spots callout (enabled by Settings -> Mining -> "Call out known planetary mining spots on arrival", which also needs "Speak callouts" on) through a late-bound SAPISpVoiceon the default audio device. This does not manipulate windows, but it is the one voice callout tied to a jump and can contend with EDCopilot's own speech. Note that this callout has no checkbox in the Voice > Callouts list (Fuel low / Scan complete / Shopping-list item), so it is easy to miss.3. Not window-related (ruled out)
Discord Rich Presence, the Twitch stream card, EDDN/Inara uploads and the mining chime also react to a jump, but they only use network/IPC/audio; none creates or alters a window.
What to try first (workaround for now)
Proposed fix
OverlayContentwith the last one and skip the update when equal; stop reassigningItemsSourceeach tick.WS_EX_NOACTIVATE(and keepTOOLWINDOW) so the overlay can never take activation, and verify with a test harness that it never becomes the foreground window.IOverlayinterface, with a no-op elsewhere), plus a setting to keep the old always-on behaviour; this keeps it from sitting over EDCopilot and other apps.Acceptance criteria
Related: #184 (position-aware overlay widgets) must not be built on the current always-on-top, self-resizing window.
🤖 Generated with Claude Code