We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4748 - Calling WIN_UpdateClipCursor() / WIN_UpdateClipCursorForWindows() on WIN_PumpEvents() causes beeping and choppy mouse cursor movement, right-click doesn't work
Summary: Calling WIN_UpdateClipCursor() / WIN_UpdateClipCursorForWindows() on WIN_Pump...
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: HG 2.1
Hardware: x86 Windows (All)
: P2 major
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords: target-2.0.12
: 4467 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-08-01 08:01 UTC by Ismael Ferreras Morezuelas (Swyter)
Modified: 2020-06-10 04:51 UTC (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ismael Ferreras Morezuelas (Swyter) 2019-08-01 08:01:27 UTC
We have bisected this regression and it is caused by revision 12154: https://hg.libsdl.org/SDL/rev/2a9b4339468b

Here is a visual example of the problem from a Windows 10 desktop machine, I have received two different reports with the same issues: https://drive.google.com/file/d/1MlQm69XcploYdPbE6CnfWOCEkpFD78A7/view


I can't reproduce it on my own machine, so I believe there is some kind of third-party software or driver-ish thing that hooks the window events and goes nuts when spamming those functions.

The issue is twofold because beeping didn't happen until r12362: https://hg.libsdl.org/SDL/rev/67496c3f9626


I can confirm that this simple patch completely fixes both the mouse choppiness + beeping and the right-click not working in windowed mode, going back to normal. Removing all the cursor-related functions from the game (SDL_ShowCursor(), SDL_SetCursor(), SDL_SetRelativeMouseMode()) didn't change anything. I don't think I am doing anything strange with the event loop or clip regions, because I only affect them indirectly through those functions. Those beeps are there even when the game's (OpenAL Soft) sound output is disabled, so it's definitely something external.


diff -r 0e3948762c96 src/video/windows/SDL_windowsevents.c
--- a/src/video/windows/SDL_windowsevents.c	Wed Jul 31 05:11:40 2019 +0300
+++ b/src/video/windows/SDL_windowsevents.c	Thu Aug 01 09:50:44 2019 +0200
@@ -1144,7 +1144,7 @@
     }
 
     /* Update the clipping rect in case someone else has stolen it */
-    WIN_UpdateClipCursorForWindows();
+    //WIN_UpdateClipCursorForWindows();
 }
 
 /* to work around #3931, a bug introduced in Win10 Fall Creators Update (build nr. 16299)



Tested with Sphinx and the Cursed Mummy, PC/Windows version. Let me know if you need Steam keys for reproducibility.

The short and sweet version is that I can't use SDL2 versions newer than 2.0.8 on Windows unless I patch that function call out myself. Even if it only affects a small subset of my customers.

Let me know if you need anything else, happy to help.
Comment 1 Ismael Ferreras Morezuelas (Swyter) 2019-08-01 08:02:46 UTC
Here is the entire bisection log to clarify things a bit:

 12968                    xx bad
r12951 is release-2.0.10  xx bad
r12373 is release-2.0.9   xx bad
 12373 (mine, debug)      xx bad
 12365 (beeps)            xx bad
 12363 (beeps)            xx bad
 12362 (beeps)            xx bad             ** https://hg.libsdl.org/SDL/rev/67496c3f9626
 12361                    xx bad -- no beeps
 12358                    xx bad -- no beeps
 12344                    xx bad -- no beeps
 12315                    xx bad -- no beeps
 12258                    xx bad -- no beeps in second try
 12244                    xx bad -- no beeps
 12230                    xx bad -- no beeps
 12202                    xx bad -- no beeps
 12201                    xx bad             (probably bad build)
 12200                    xx bad -- no beeps
 12199                    xx bad -- no beeps
 12197                    xx bad -- no beeps
 12193                    xx bad -- no beeps
 12186                    xx bad -- no beeps
 12172                    xx bad -- no beeps
 12158                    xx bad -- no beeps
 12154                    xx bad -- no beeps ** https://hg.libsdl.org/SDL/rev/2a9b4339468b <--
 12153                    -- good            ** https://hg.libsdl.org/SDL/rev/de4288fa5b0b
 12152                    -- good
 12151                    -- good
 12144                    -- good
 12029                    -- good
r11915 is release-2.0.8   -- good
Comment 2 Ozkan Sezer 2019-09-03 22:10:29 UTC
This one should be 'target-2.0.11'
Comment 3 Ryan C. Gordon 2019-09-20 20:47:35 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.
Comment 4 Ryan C. Gordon 2019-09-20 20:48:44 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.
Comment 5 Sylvain 2019-10-23 07:04:35 UTC
Not the same bisect but maybe this is helped by
https://hg.libsdl.org/SDL/rev/9d6107cbcd66

Related to bug 4841
Comment 6 Sylvain 2019-10-23 13:03:41 UTC
*** Bug 4467 has been marked as a duplicate of this bug. ***
Comment 7 Ismael Ferreras Morezuelas (Swyter) 2019-10-24 20:32:43 UTC
I can confirm that the original tester from the video above has tested a 32-bit r13170 version of SDL2.dll that I compiled myself and the game seems to function normally both in fullscreen and windowed mode.

Keep in mind that I haven't bisected the changes to see if that specific revision was the one that fixes the regression. But it seems likely, thanks again. :)

Now I can keep the Windows version of SDL2 up to date again.
Comment 8 Ismael Ferreras Morezuelas (Swyter) 2019-10-24 21:01:53 UTC
Well, false alarm. After confirming that SDL2-r13170.dll works fine I gave him a SDL2-r13163-v2.dll (twice) and it also worked fine, he then retested the original SDL2-r12258-v2.dll (which is a known bad revision) and it also worked smoothly.

Meaning that (due to Windows 10 updates or something else) the problem is gone on that rig and we can't reproduce the issue or that it has been fixed, last time he tested it was on 31/07/2019. Darn.


He argues that it's related to this recent Windows 10 update, but it may be something entirely different: https://cdn.discordapp.com/attachments/393832574516199424/637031169564868608/unknown.png

I'll try to contact the other player and see if we can consistently reproduce it, or the heisenbug is gone.
Comment 9 Ryan C. Gordon 2019-11-04 05:03:43 UTC
(In reply to Ismael Ferreras Morezuelas (Swyter) from comment #8)
> I'll try to contact the other player and see if we can consistently
> reproduce it, or the heisenbug is gone.

There is a known beeping bug (which is what Windows does to signify that the system's input queue is overflowing) like this related to an XInput driver, fwiw...

https://www.reddit.com/r/Windows10/comments/7nw918/xinput_mouse_beepinglagging_and_desktop_freezing/

I'm not saying that's what's happening here, but that this might not be a widespread issue and also might be completely beyond our control. We might just have to close this and see if other reports pop up later.

If you're wondering why it's _beeping_, here's the likely technical explanation (if a hardware driver is hanging, I assume that causes this problem too, instead of the 16-bit Windows thing he mentions)...

https://devblogs.microsoft.com/oldnewthing/20090918-00/?p=16663

--ryan.
Comment 10 Ryan C. Gordon 2019-12-04 15:57:17 UTC
If there's no further comment on this bug, I believe I will be closing it in the next few days, under the assumption that it's the XInput driver bug I mentioned.

--ryan.
Comment 11 Rémy Tassoux 2019-12-04 18:08:44 UTC
For me, this bug is triggered when I call the SDL_SetWindowGrab function (see bug 4467), but only after the 2.0.8 version (not included). The Win32 function  ClipCursor is what the SDL2 is using under the hood to grab the cursor inside the window, and from my understanding it's not related at all to XInput. Moreover, as a workaround of this bug, I wrote my own Windows version of SDL_SetWindowGrab using the Win32 function ClipCursor, and everything works fine.

#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <Windows.h>

void custom_window_grab( SDL_Window* window, bool clip )
{
    if ( clip )
    {
        int x{};
        int y{};
        int width{};
        int height{};
        SDL_GetWindowPosition( window, &x, &y );
        SDL_GetWindowSize( window, &width, &height );
        RECT rect{ x, y, x + width, y + height };
        ClipCursor( &rect );
    }
    else
    {
        ClipCursor( nullptr );
    }
}

int main()
{
    SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS );

    auto window = SDL_CreateWindow(
        "Window",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        800,
        600,
        SDL_WINDOW_RESIZABLE
    );

    // SDL_SetWindowGrab( window, SDL_TRUE ); // Slow and choppy cursor
    custom_window_grab( window, true ); // Works perfectly

    bool run{ true };
    while ( run )
    {
        SDL_Event event{};
        SDL_PollEvent( &event );

        if ( event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE )
        run = false;

    }

    SDL_DestroyWindow( window );

    return 0;
}
Comment 12 Sam Lantinga 2020-02-11 18:08:46 UTC
Fixed, thanks!
https://hg.libsdl.org/SDL/rev/d5109d6a9b98
Comment 13 Dom 2020-02-12 19:55:41 UTC
(In reply to Sam Lantinga from comment #12)
> Fixed, thanks!
> https://hg.libsdl.org/SDL/rev/d5109d6a9b98

Based on that commit message, shouldn't the same also be done in case of relative mouse mode a few lines above?
Comment 14 Sam Lantinga 2020-02-12 20:26:47 UTC
(In reply to Dom from comment #13)
> (In reply to Sam Lantinga from comment #12)
> > Fixed, thanks!
> > https://hg.libsdl.org/SDL/rev/d5109d6a9b98
> 
> Based on that commit message, shouldn't the same also be done in case of
> relative mouse mode a few lines above?

You're right, thanks!
https://hg.libsdl.org/SDL/rev/529fc1a611e8
Comment 15 Dom 2020-02-12 20:48:52 UTC
(In reply to Sam Lantinga from comment #14)
> You're right, thanks!
> https://hg.libsdl.org/SDL/rev/529fc1a611e8

I think this changed the logic of the previous commit. Before ClipCursor() was called in case of !GetClipCursor() || memcmp() != 0 for mouse grab. Now the function already returns at the start in case of !GetClipCursor().
Comment 16 Sam Lantinga 2020-02-13 17:50:51 UTC
Yes, that's correct. We don't change the clip state if we can't get the current clip cursor, which should only happen if we don't have read access to the display.
Comment 17 Richard Gobeille 2020-05-14 10:06:28 UTC
On my system, it's the call to GetClipCursor that is slow--we have been experiencing an issue with every version of SDL newer than 2.0.8 where a mouse polling rate higher than around 500Hz results in a noticeable frame time increase while moving the mouse; profiling the code indicated that the time was spent in the NtUserGetClipCursor kernel call that backs the GetClipCursor function.

I am going to test Rémy's idea of bypassing SDL_SetWindowGrab and see where that gets me.
Comment 18 Dom 2020-06-07 07:09:36 UTC
Yes, this is still an issue as of 2.0.12. See Bug 5171.

Maybe the original commit https://hg.libsdl.org/SDL/rev/2a9b4339468b causing this issue should be reverted along with the commits https://hg.libsdl.org/SDL/rev/d5109d6a9b98 and https://hg.libsdl.org/SDL/rev/529fc1a611e8 trying to fix it.
Comment 19 Cameron Gutman 2020-06-07 18:43:16 UTC
I agree those should be reverted. In addition to the performance regression, I believe there's a correctness issue too.

Consider the case of another app showing a window on top of SDL's and calling ClipCursor(). SDL will immediately steal the cursor clip region back, but the focus stealing app's window is still on top of SDL's. The effect you get is that the cursor in the focus stealing app's window is confined to the clip region dictated by the SDL window behind it, which may not even be visible at all anymore.
Comment 20 Sam Lantinga 2020-06-10 04:51:07 UTC
Fixed, thanks!
https://hg.libsdl.org/SDL/rev/ff702ce6ab48

Cameron, the scenario you're talking about shouldn't happen due to the SDL_WINDOW_INPUT_FOCUS check in WIN_UpdateClipCursor(). If you're seeing that happen anyway, please submit a new bug and let us know how SDL_WINDOW_INPUT_FOCUS gets out of sync with the actual window state.