Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_SetWindowGrab doesn't work with mouse not hidden (SDL2, X11 video driver only) #9162

Closed
ell1e opened this issue Feb 27, 2024 · 6 comments
Labels
notourbug This bug is caused by an external component
Milestone

Comments

@ell1e
Copy link
Contributor

ell1e commented Feb 27, 2024

SDL_SetWindowGrab doesn't work with the mouse cursor still shown. The mouse is only confined to the window if SDL_ShowCursor is also set to SDL_FALSE, but the documentation of SDL_SetWindowGrab seems to claim that's not an intended precondition:

When input is grabbed, the mouse is confined to the window.

(Note no mention that the confinement depends on the mouse cursor being hidden.)

This is at least broken when using SDL 2.30.0-1.1 as packaged by OpenSUSE with KDE Plasma Shell 5.27.10 with a Wayland session, SDL defaulting to SDL_VIDEODRIVER=x11 with this setup. Not sure about whether this actually works on other platforms.

Edit: Here's code to reproduce it:


#include <SDL2/SDL.h>
#include <stdio.h>

int main(int argc, const char **argv) {
    SDL_Window *window = NULL;
    if (SDL_Init(SDL_INIT_VIDEO) < 0) return 1;
    window = SDL_CreateWindow("Test",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        200, 200, SDL_WINDOW_SHOWN);
    if (window == NULL) return 1;
    SDL_SetWindowGrab(window, SDL_TRUE);

    int hadsurfaceupdate = 0;
    printf("Window should now be visible.\n");
    while (1) {
        SDL_Event e;
        while (SDL_PollEvent(&e) != 0) {
            if (e.type == SDL_MOUSEMOTION) {
                printf("Mouse at: %d, %d\n",
                    (int)e.motion.x, (int)e.motion.y);
            } else if (e.type == SDL_WINDOWEVENT) {
                if (e.window.event == SDL_WINDOWEVENT_ENTER) {
                    printf("Mouse enters window.\n");
                } else if (e.window.event == SDL_WINDOWEVENT_LEAVE) {
                    printf("Mouse leaves window.\n");
                }
            }
        }

        SDL_Surface *srf = SDL_GetWindowSurface(window);
        SDL_UpdateWindowSurface(window);
        if (!hadsurfaceupdate) {
            printf("First surface update done.\n");
            hadsurfaceupdate = 1;
        }
    }
    return 0;
}

What happens, with the expected behavior that the mouse cursor is trapped to the window at least as long as the window has focus (I click it during the runtime of the video but it doesn't make any difference):

bug-sdl2-nomouseconfinement.webm
@ell1e ell1e changed the title SDL_SetWindowGrab doesn't work with mouse not hidden SDL_SetWindowGrab doesn't work with mouse not hidden (SDL2) Feb 27, 2024
@ell1e
Copy link
Contributor Author

ell1e commented Feb 27, 2024

Thanks to this helpful comment I was able to test confinement with SDL_VIDEODRIVER=wayland where it works. So this is an SDL_VIDEODRIVER=x11-with-Plasma-Wayland/XWayland bug, it seems like.

Sadly, many distributions still seem to ship SDL2 with SDL_VIDEODRIVER=x11 as a default and probably also without libdecor. Therefore, this bug still seems relevant today.

@ell1e ell1e changed the title SDL_SetWindowGrab doesn't work with mouse not hidden (SDL2) SDL_SetWindowGrab doesn't work with mouse not hidden (SDL2, X11 video driver only) Feb 27, 2024
@slouken slouken added this to the 2.32.0 milestone Mar 3, 2024
@slouken
Copy link
Collaborator

slouken commented Mar 3, 2024

@Kontrabant, is this possible to fix when XWayland is in use?

@Kontrabant
Copy link
Contributor

Will look into this, although this might be a KDE bug, as it works fine on GNOME with XWayland.

@Kontrabant
Copy link
Contributor

Something is definitely broken in KDE. When grabbing on my test system (Fedora 39 with all updates), the cursor is blocked on the sides and bottom, but can escape from the top in both this sample and when grabbing via ctrl+G in testsprite. When the cursor escapes from the top, no leave event occurs and mouse events continue to arrive when moving the mouse, even though the cursor is not over the window anymore.

Note that on both GNOME and KDE, if a grab is initiated while the cursor is outside of the window, it won't be confined until the mouse is clicked while the cursor over the window. I'm guessing this is some internal XWayland behavior since it happens regardless of desktop.

This needs to go upstream, as there's nothing that SDL can do to fix this.

@Kontrabant Kontrabant added the notourbug This bug is caused by an external component label Mar 4, 2024
@ell1e
Copy link
Contributor Author

ell1e commented Mar 5, 2024

Thanks so much for looking into this! I filed a KDE bug here: https://bugs.kde.org/show_bug.cgi?id=482448

@ell1e
Copy link
Contributor Author

ell1e commented Mar 5, 2024

Since it seems like this is being fixed in KWin/KDE now, I'll close this here! Thanks again for your help.

@ell1e ell1e closed this as completed Mar 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
notourbug This bug is caused by an external component
Projects
None yet
Development

No branches or pull requests

3 participants