Share via

XInput on Windows 10+: Gamepad controller stops rumbling after using Alt-Tab back and forth

Lars-4325 20 Reputation points
2026-05-31T11:59:21.29+00:00

I'm writing a C/C++ application based on the win32 API along with XInput.

Issue:

I'm using XInputSetState once to set the rumble motors speed, however they stop when the app loses the focus even if it regains it after that. I would expect that regaining the focus would restart the motors automatically.

Some context:

On Windows 8 you could use XInputEnable (which is now deprecated), which works as I expected when used like this in the WindowProc:

case WM_ACTIVATEAPP:

XInputEnable(!wParam);

break;

Now the documentation claims the following:

Windows 10 or later: Deprecated, as game controller input is automatically enabled/disabled by the system based on the application window focus.

https://learn.microsoft.com/en-us/windows/win32/api/xinput/nf-xinput-xinputenable

However, it doesn't work the same. XInputEnable(true) enables the rumble motors back to the previous values, which is not happening here.

What I tested:

1 - I tried to manually call XInputSetState within WM_ACTIVATEAPP when wParam is 1. Sometimes it seems to work for a millisecond, but the new behavior kicks in again and disables the vibration.

2 - Also, I tried the same from the program main loop:

while (is_running) {

while (PeekMessage(...)) { TranslateMessage(...); DispatchMessage(...); }

if (app_gained_focus) { ... XInputSetState(...); }

SwapBuffers(...);

}

Same as before, no luck. I bet it would work if I wait for several frames before doing that, but it is not reliable.

Additional remarks:

Not only the vibration does not work as expected. I can still poll the controller with XInputGetState and it doesn't report neutral values. The buttons I press are registered even when the app isn't focused, unlike with XInputEnable(false).

Luckily, I can work around that.

Questions:

  • Is this a bug, i.e., are rumble motors supposed to get restarted when regaining focus?
  • What's the proper workaround to restart them when regaining focus without spamming XInputSetState?

Thanks in advance!

Windows development | Windows API - Win32
0 comments No comments

Answer accepted by question author

Taki Ly (WICLOUD CORPORATION) 2,225 Reputation points Microsoft External Staff Moderator
2026-06-01T03:30:25.2466667+00:00

Hello @Lars-4325 ,

Thank you for the detailed context and for sharing the troubleshooting steps you've already taken.

Regarding whether this should be considered a bug, while I can't definitively call it one since there isn't deep official documentation on its under-the-hood implementation, this is a known behavior that many developers have encountered. It seems that the OS-level service responsible for the automatic focus management operates asynchronously from the application's UI thread. When WM_ACTIVATEAPP is triggered, the background system might still be in the process of zeroing out the controller state. Because of this slight timing difference, if you call XInputSetState immediately inside the window message, your command likely gets overridden by the OS completing its automated "clear" sequence. Additionally, it appears the system simply doesn't cache the previous vibration values to restore them for you.

To handle this without constantly polling or spamming XInputSetState, I suggest trying a deferred execution (or delay) pattern. Instead of applying the rumble state immediately upon regaining focus, you can set a flag and wait for a short duration (e.g., 50 to 100 milliseconds, or a few frames) in your main loop. This gives the OS enough time to finish its background transition before you re-apply your cached vibration state.

I suggest incorporating a logic pattern similar to this:

// Globals or class members to cache the state
XINPUT_VIBRATION current_vibration = {0};
bool app_has_focus = true;
bool need_vibration_restore = false;
DWORD focus_regain_time = 0;
// Inside your WindowProc:
case WM_ACTIVATEAPP:
    app_has_focus = (wParam == TRUE);
    if (app_has_focus) {
        need_vibration_restore = true;
        focus_regain_time = GetTickCount(); // Record the time focus was regained
    } else {
        // Optional: explicitly zero-out vibration when losing focus to be safe
        XINPUT_VIBRATION zero_vib = {0};
        XInputSetState(0, &zero_vib);
    }
    break;
// Inside your main game loop:
void UpdateGamepad() {
    if (!app_has_focus) {
        // Skip polling to prevent "bleeding" inputs while in the background
        return; 
    }
    // Restore vibration after a short, safe delay (e.g., 100ms)
    if (need_vibration_restore) {
        if (GetTickCount() - focus_regain_time > 100) { 
            XInputSetState(0, &current_vibration); 
            need_vibration_restore = false;
        }
    }
    // Normal game logic to update rumble based on gameplay goes here...
}

As a side note, if your project is heavily focused on Windows 10 and newer, you might want to look into the modern Windows.Gaming.Input API down the line. It handles background/foreground focus transitions and modern controller features much more gracefully than legacy XInput.

I hope this helps point you in the right direction. Let me know if the delayed approach works for your main loop. If you found my response helpful or informative, I would greatly appreciate it if you could follow this guide for your confirmation.

Thank you.

Was this answer helpful?

2 people found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.