All notable changes to the Playnite Overlay plugin will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Migrated controller input from custom SDL2 P/Invoke to Playnite SDK 6.16 controller events
- Removed bundled SDL2.dll and gamecontrollerdb.txt (no longer needed)
- Requires Playnite 10.52+ (previously 6.12.0+)
- Requires "Enable controller support in Desktop mode" in Playnite Settings → Input
- Removed "Controller Always Active" setting (controller events are always delivered by Playnite)
- Controller input not working since v0.7.0 (#47)
- Overlay crashes Playnite when using with ControlUp addon (#52)
- SDL2 Controller Support: Full support for all SDL2-compatible controllers
- PlayStation DualShock 4 and DualSense (PS5) controllers
- Nintendo Switch Pro Controller
- 8BitDo and other third-party controllers
- 2220+ controller mappings from community database
- Replaces XInput-only support for broader compatibility
- Overlay Shortcuts: Custom shortcut buttons in the overlay
- Configure up to 10 custom shortcuts in settings
- Two action types: CommandLine (run scripts/exe) and SendInput (simulate hotkeys)
- Shortcuts appear in a dedicated SHORTCUTS section
- Perfect for screenshots, recording, or launching external tools
- 2D Navigation: Navigate shortcuts grid with D-pad or arrow keys
- Horizontal and vertical movement between shortcut buttons
- Seamless integration with existing navigation system
- Improved Focus Stealing: Cascading fallback techniques for reliable game focus
- Three techniques tried in order: AttachThreadInput, Alt key simulation, Foreground lock timeout
- Each technique verifies success before trying next fallback
- Better compatibility with stubborn fullscreen games
- Crash Recovery: Process suspension now tracks all suspended processes
- Games won't be left frozen if Playnite crashes
- Automatic resume on plugin dispose
- Retry logic (up to 3 attempts) for resume failures
- Thread Safety: Added proper synchronization for process suspension state
- Type Safety: Replaced string-based FocusControlMode with enum
- Per-App Volume Control: Adjust volume for individual running applications directly from the overlay
- Shows volume slider for each running app in the RUNNING APPS section
- Uses NAudio for per-process audio control
- Mute/unmute toggle for each app
- Time and Playtime Display: Real-time clock and session duration now shown in overlay header
- Current time displayed in 12-hour format (e.g., "3:45 PM")
- Session duration updates live when a game is active ("Playing for 2h 15m")
- Audio Device Switcher: Switch default Windows audio output device directly from the overlay
- Shows dropdown with all active audio output devices
- Displays current default device with indicator
- Auto-hides when no audio devices detected or NAudio fails to initialize
- Uses NAudio 2.2.1 for device enumeration
- Switches device for all roles (Multimedia, Console, Communications)
- Show Notifications Toggle: New setting to enable/disable all overlay notifications (app switching, exit operations, errors).
- PC Games Only Mode: Option to disable controller input for non-PC games
- Useful when emulators have their own overlays (RetroArch, etc.)
- Works with all controller settings (Controller Always Active enabled or disabled)
- Keyboard hotkey continues to work for all games regardless of this setting
- Games without platform metadata are treated as PC games (backward compatible)
- New setting:
PcGamesOnly(default: disabled for backward compatibility) - Tip: Set platform metadata for emulated games to prevent controller conflicts
- SuccessStory Integration: Display achievement progress in the NOW PLAYING section
- Shows achievement progress (X/Y - Z%) when SuccessStory plugin is installed
- Displays recently unlocked achievements with gold trophy icon
- Shows locked achievements with lock icon
- New settings:
ShowAchievements,MaxRecentAchievements,MaxLockedAchievements - Gracefully hidden when SuccessStory is not installed or game has no achievement data
- Show Generic Apps Default: Changed default from enabled to disabled. New installations will only show Playnite-tracked games by default.
- SuccessStory Achievement Detection: Fixed locked achievements incorrectly showing as unlocked
- SuccessStory uses
0001-01-01date to represent locked achievements - Plugin now correctly identifies locked vs unlocked achievements
- SuccessStory uses
- Hide Running Apps from Recent Games: Running games no longer appear in both "Running Apps" and "Recent Games" sections
- Prevents duplicate entries in the overlay UI
- Recent games list now excludes any games currently shown in Running Apps
- D-pad and Button Double-Navigation: Fixed controller inputs triggering multiple times per press
- Affected users with controllers that register as multiple XInput devices
- Added per-poll-cycle flag to prevent duplicate navigation events
- Window Switching Reliability: Improved app switching behavior
- Better handling of window focus transitions
- More reliable foreground window detection
- System Tray Restore: Fixed black screen when restoring Playnite from system tray
- Properly handles minimized-to-tray state
- Thread-Safe Event Invocation: Fixed potential race condition in event handlers
- XInput Polling Consolidation: Refactored controller input handling into single polling loop
- Cleaner code structure
- More efficient input processing
- WPF Simplification: Refactored overlay to use more native WPF features
- Input Blocking in Fullscreen Games: Keyboard input now properly blocked when overlay is active
- Use low-level keyboard hook (
WH_KEYBOARD_LL) to intercept input before it reaches games - Added mouse click blocking support
- Use low-level keyboard hook (
- Xbox Guide Button Detection: Fixed Guide button not being detected
- Use
XInputGetStateEx(ordinal 100) which includes the Guide button - Falls back to standard API on older systems
- Use
- Removed Toggle Overlay Menu Item: The "Overlay → Toggle Overlay" menu item has been removed
- Overlay can still be toggled via keyboard hotkey (default: Ctrl+Shift+O)
- Overlay can still be toggled via controller (Guide button or configured combo)
- Dead Code Cleanup: Removed ~200 lines of unused/duplicate code
- Removed unused XInput keystroke API
- Removed legacy OverlayUI project
- Consolidated duplicate code into
ProcessMatchingUtils - Removed unused
TertiaryTextproperty from OverlayItem
- Fullscreen Games Minimizing: Overlay no longer steals focus from games
- Added
WS_EX_NOACTIVATEandWS_EX_TOOLWINDOWextended window styles - Use
SetWindowPoswithSWP_NOACTIVATEfor topmost positioning - Overlay now appears on same monitor as the foreground game
- Added
- Button Focus Visibility: Focus border now appears reliably on all buttons
- Changed from
IsFocusedtoIsKeyboardFocusedtriggers - Use
Keyboard.ClearFocus()when exiting to section level
- Changed from
- Controller Navigation: Complete navigation system rewrite
- Full support for
RunningAppsListnavigation (was previously ignored) - Fixed initial focus priority: RunningApps → RecentList → SwitchButton
- Navigation now flows logically through entire overlay UI
- Full support for
- Dual Selection Highlight: Only one item highlighted at a time across lists
- Nullable Reference Warnings: Fixed compiler warnings in GameSwitcher and RunningAppsDetector
- Force Borderless Mode: Optional feature for games that still minimize
- Automatically converts windowed games to borderless fullscreen
- Configurable delay before applying (default: 3 seconds)
- Restores original window state when game exits
- New settings:
ForceBorderlessMode,BorderlessDelayMs
- Two-Level Navigation System: Section-first navigation for controller/keyboard
- Level 1: Navigate between sections (CurrentGame, RunningApps, RecentGames) with Up/Down
- Level 2: Press Enter/A to drill into section, navigate items with Up/Down
- Press Escape/B to exit back to section level
- Keyboard Arrow Navigation: Arrow keys now work for overlay navigation
- Up/Down arrows navigate through sections and items
- Left/Right arrows navigate between buttons
- Enter key activates the currently selected item
- Button Focus Visual Feedback: White border on all focused buttons
- Diagnostic Logging: Debug logging for controller input events
- Controller Always Active: Now defaults to
true(works without game running) - Navigation Flow: Improved controller/keyboard navigation UX
- Section-level navigation with visual border feedback
- Item-level navigation within sections
- Automatic scroll-into-view for selected items
- Active App Tracking System: Plugin now tracks which game/app you're currently focused on
- Session duration display ("Playing for 2h 15m")
- Total playtime tracking for Playnite games
- Single source of truth for active app state
- Auto-Detection Feature: Automatically detects foreground app when opening overlay
- Smart detection when no active app is set
- Auto-switches to new app after exiting current one
- Uses Win32 APIs (
GetForegroundWindow,GetWindowThreadProcessId)
- Running Apps Detection: Three-tier detection system for all running applications
- Playnite-tracked games (launched through Playnite)
- Detected games (manually launched, matched to library)
- Generic apps (browsers, editors, etc.) - optional
- Configurable visibility and limits
- Three-Section Overlay UI: New layout with distinct sections
- NOW PLAYING: Shows active game with session info
- RUNNING APPS: Lists all detected running apps with "Switch" buttons
- RECENT GAMES: Shows 5 most recently played games
- New Settings:
ShowGenericApps: Toggle visibility of non-game applications (default: true)MaxRunningApps: Limit number of running apps displayed (1-50, default: 10)ControllerAlwaysActive: Keep controller input active even when not gaming (default: false)
- Split Input Lifecycle: Hotkey and controller now have independent lifecycles
- Hotkey always active (works even when not gaming)
- Controller configurable (always-active or gameplay-only)
- Simplified Architecture: Refactored from dual tracking to single tracking
- Removed
CurrentGame/CurrentGameStartTime(Playnite tracking) - Unified to
ActiveApponly as single source of truth - Added
ActivatedTimeandTotalPlaytimetoRunningAppmodel - Reduced
ToggleOverlay()complexity by ~33% (~100 lines simpler)
- Removed
- Improved Process Detection: Three-strategy matching system
- Install directory matching (primary)
- Process name fuzzy matching (secondary)
- Window title matching (tertiary)
- Enhanced Error Handling: Better crash prevention and user feedback
- Race condition protection when processes exit during operations
- Graceful degradation when access denied
- Clear notification messages for all operations
- Hotkey Lifecycle Bug: Hotkey now works at all times, not just during gameplay
- Previously stopped working after game exit due to tied lifecycle
- Split from controller input lifecycle for independent operation
- .NET Framework 4.7.2 Compatibility: Resolved all compatibility issues
- Removed WPF features not available in .NET Framework 4.7.2
- Tested and verified on target runtime
- Race Condition Crashes: Fixed crash when process exits before switch operation
- Added window existence validation (
IsWindow()) - Proper error handling in
SwitchToApp()
- Added window existence validation (
- Process Termination Edge Cases: Improved game exit logic
- Better handling of launcher processes (Steam, Epic, etc.)
- Graceful → forceful termination with proper timeouts (3s → 1s)
- Admin permission handling with clear user guidance
- Code Cleanup: Removed unused imports and dead code
- Removed
using System.IO;from GameSwitcher (unused) - Verified all methods are called and imports are needed
- Removed
- Test Coverage: Added comprehensive unit tests
ComboMaskTests: Controller combo mask resolutionGameSwitcherTests: Core game management logicInputListenerTests: Input handlingOverlayItemTests: Data model factory methods
- CI/CD Pipelines: Added GitHub Actions workflows
ci.yml: Main CI pipeline for feature branchesci-develop.yml: Develop branch pipelineci-debug.yml: Debug diagnostics pipelinerelease-main.yml: Production release pipeline
- Documentation: Complete documentation overhaul
- New
README.md: User-friendly guide - Updated
AGENTS.md: Comprehensive developer guide - New
CHANGELOG.md: Version history tracking
- New
- Architecture Refactoring: Single tracking implementation
- Before: Dual tracking with
CurrentGame+ActiveApp(complex state) - After: Single
ActiveApptracking (simple, clear mental model) - Result: Fewer edge cases, easier maintenance, better UX
- Before: Dual tracking with
- Service Responsibilities:
GameSwitcher: Active app management, process detection, game launching/terminationRunningAppsDetector: Multi-app detection, window validation, switchingOverlayService: UI lifecycle managementInputListener: Input handling with split hotkey/controller lifecycle
- Data Models:
RunningApp: AddedActivatedTime(DateTime) andTotalPlaytime(ulong seconds)OverlayItem: Factory methods for different UI sectionsAppType: Enum for three-tier classification (PlayniteGame | DetectedGame | GenericApp)
- None at release
(Version 0.2.0 and earlier are not documented in this changelog. See git history for details.)
- Added: New features
- Changed: Changes in existing functionality
- Deprecated: Soon-to-be removed features
- Removed: Removed features
- Fixed: Bug fixes
- Security: Vulnerability fixes