Bug with SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_FULLSCREEN

[Ryan C. Gordon, May^WJune^WJuly is SDL release month!]

If you have a bug that isn’t on that list: speak up now. We can add to
the list, but only if we know your bug should be on it.

I’ve upgraded from SDL 1.2.15 to 2.0 (built from June 21’s sources from hg)
and I love it, especially SDL_WINDOW_FULLSCREEN_DESKTOP which is the
greatest thing ever and the fact that the Windows system cursor isn’t
replaced, but I believe I’ve discovered a bug. I’ve prepared a
self-contained test case here, and I can even provide my entire build
environment if necessary. I’m running MinGW (32-bit) on Win7 x64, with dual
2560x1600 monitors.

What I observe is that FlagsWindowed, FlagsFullscreen, and FlagsDesktop
(defined below) work perfectly. The cursor isn’t grabbed so it’s free to
leave the window and travel to the other monitor. Clicking inside the window
triggers SDL_MOUSEBUTTONUP and stops the color-changing whose sole purpose
is to indicate that a click has been registered. (SDL 1.2’s behavior was
different, in that fullscreen mode grabbed the cursor. SDL 2.0’s
not-grabbing by default is perfectly fine, as long as I can request grabbing

  • which is how I discovered this.)

I additionally observe that FlagsGrabbedWindowed and
FlagsGrabbedFocusedWindowed work correctly. The cursor is grabbed so it
can’t leave the window, and clicking immediately triggers the event and
stops the color-changing.

The bug is that FlagsGrabbedFullscreen, FlagsGrabbedDesktop,
FlagsGrabbedFocusedFullscreen, and FlagsGrabbedFocusedDesktop behave
strangely. The cursor is indeed grabbed so it can’t travel to the other
monitor, and the fullscreen window is rendered on top of everything else
(including an AutoHide taskbar), but the window does not behave as if it is
truly on top of everything else. In particular, if other windows are open
behind it (e.g. Notepad, a Command Prompt, whatever) the cursor will change
from an ordinary pointer to a double-headed resize arrow when it’s hovering
over the other windows’ edges. This is not just a cosmetic cursor defect -
clicking will send the click to whatever window happens to be underneath,
minimizing the SDL program to the taskbar. After clicking on the SDL program
in the taskbar to restore it, the color-changing is still running,
indicating that it didn’t receive the click. However, the restoring process
"fixes" whatever was wrong with the window - the mouse is grabbed and
clicking works normally.

I am not sure what SDL_WINDOW_INPUT_FOCUS and SDL_WINDOW_MOUSE_FOCUS are
supposed to do, but their absence/presence doesn’t seem to affect anything.

Here is my code (dramatically simplified from my actual game engine, with
all error-checking and other libraries eliminated):

// g++ -Wall -Wextra -mthreads -mwindows meow.cpp -o meow.exe -lopengl32
-lSDL2 -limm32 -lole32 -loleaut32 -luuid -lversion -lwinmm -lmingw32
-lSDL2main

#include <GL/gl.h>
#include <SDL2/SDL.h>

const Uint32 FlagsWindowed = 0;
const Uint32 FlagsFullscreen = SDL_WINDOW_FULLSCREEN;
const Uint32 FlagsDesktop = SDL_WINDOW_FULLSCREEN_DESKTOP;
const Uint32 FlagsGrabbedWindowed = SDL_WINDOW_INPUT_GRABBED;
const Uint32 FlagsGrabbedFullscreen = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_FULLSCREEN;
const Uint32 FlagsGrabbedDesktop = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_FULLSCREEN_DESKTOP;
const Uint32 FlagsGrabbedFocusedWindowed = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS;
const Uint32 FlagsGrabbedFocusedFullscreen = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_FULLSCREEN;
const Uint32 FlagsGrabbedFocusedDesktop = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS |
SDL_WINDOW_FULLSCREEN_DESKTOP;

int main(int, char * []) {
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

#ifndef MY_WIDTH
    #define MY_WIDTH 1920
#endif

#ifndef MY_HEIGHT
    #define MY_HEIGHT 1200
#endif

#ifndef MY_FLAGS
    #define MY_FLAGS FlagsWindowed
#endif

SDL_Window * window = SDL_CreateWindow("Meow", SDL_WINDOWPOS_CENTERED,

SDL_WINDOWPOS_CENTERED, MY_WIDTH, MY_HEIGHT, SDL_WINDOW_OPENGL | MY_FLAGS);
SDL_GLContext context = SDL_GL_CreateContext(window);
bool changing = true;
const Uint64 freq = SDL_GetPerformanceFrequency();

for (bool keep_going = true; keep_going; ) {
    for (SDL_Event event; SDL_PollEvent(&event); ) {
        switch (event.type) {
            case SDL_KEYDOWN:
            case SDL_QUIT:
                keep_going = false;
                break;
            case SDL_MOUSEBUTTONUP:
                changing = !changing;
                break;
            default:
                break;
        }
    }

    if (changing) {
        const double d = (SDL_GetPerformanceCounter() % freq) * 1.0 /

freq;
glClearColor(d, d, d, 1.0);
}

    glClear(GL_COLOR_BUFFER_BIT);
    SDL_GL_SwapWindow(window);
}

SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;

}

I have provided the Flags* constants and MY_* macros for convenience, so you
can build the test case with varying command lines like:

g++ -Wall -Wextra -mthreads -mwindows meow.cpp -o meow.exe -lopengl32 -lSDL2
-limm32 -lole32 -loleaut32 -luuid -lversion -lwinmm -lmingw32 -lSDL2main
-DMY_FLAGS=FlagsGrabbedDesktop

instead of repeatedly altering the file.

Thanks,
Stephan T. Lavavej

This is a great bug report. Can you submit it to bugzilla along with your
test program?
http://bugzilla.libsdl.org

Thanks!On Fri, Jul 12, 2013 at 10:56 PM, Stephan T. Lavavej wrote:

[Ryan C. Gordon, May^WJune^WJuly is SDL release month!]

If you have a bug that isn’t on that list: speak up now. We can add to
the list, but only if we know your bug should be on it.

I’ve upgraded from SDL 1.2.15 to 2.0 (built from June 21’s sources from hg)
and I love it, especially SDL_WINDOW_FULLSCREEN_DESKTOP which is the
greatest thing ever and the fact that the Windows system cursor isn’t
replaced, but I believe I’ve discovered a bug. I’ve prepared a
self-contained test case here, and I can even provide my entire build
environment if necessary. I’m running MinGW (32-bit) on Win7 x64, with dual
2560x1600 monitors.

What I observe is that FlagsWindowed, FlagsFullscreen, and FlagsDesktop
(defined below) work perfectly. The cursor isn’t grabbed so it’s free to
leave the window and travel to the other monitor. Clicking inside the
window
triggers SDL_MOUSEBUTTONUP and stops the color-changing whose sole purpose
is to indicate that a click has been registered. (SDL 1.2’s behavior was
different, in that fullscreen mode grabbed the cursor. SDL 2.0’s
not-grabbing by default is perfectly fine, as long as I can request
grabbing

  • which is how I discovered this.)

I additionally observe that FlagsGrabbedWindowed and
FlagsGrabbedFocusedWindowed work correctly. The cursor is grabbed so it
can’t leave the window, and clicking immediately triggers the event and
stops the color-changing.

The bug is that FlagsGrabbedFullscreen, FlagsGrabbedDesktop,
FlagsGrabbedFocusedFullscreen, and FlagsGrabbedFocusedDesktop behave
strangely. The cursor is indeed grabbed so it can’t travel to the other
monitor, and the fullscreen window is rendered on top of everything else
(including an AutoHide taskbar), but the window does not behave as if it is
truly on top of everything else. In particular, if other windows are open
behind it (e.g. Notepad, a Command Prompt, whatever) the cursor will change
from an ordinary pointer to a double-headed resize arrow when it’s hovering
over the other windows’ edges. This is not just a cosmetic cursor defect -
clicking will send the click to whatever window happens to be underneath,
minimizing the SDL program to the taskbar. After clicking on the SDL
program
in the taskbar to restore it, the color-changing is still running,
indicating that it didn’t receive the click. However, the restoring process
"fixes" whatever was wrong with the window - the mouse is grabbed and
clicking works normally.

I am not sure what SDL_WINDOW_INPUT_FOCUS and SDL_WINDOW_MOUSE_FOCUS are
supposed to do, but their absence/presence doesn’t seem to affect anything.

Here is my code (dramatically simplified from my actual game engine, with
all error-checking and other libraries eliminated):

// g++ -Wall -Wextra -mthreads -mwindows meow.cpp -o meow.exe -lopengl32
-lSDL2 -limm32 -lole32 -loleaut32 -luuid -lversion -lwinmm -lmingw32
-lSDL2main

#include <GL/gl.h>
#include <SDL2/SDL.h>

const Uint32 FlagsWindowed = 0;
const Uint32 FlagsFullscreen = SDL_WINDOW_FULLSCREEN;
const Uint32 FlagsDesktop = SDL_WINDOW_FULLSCREEN_DESKTOP;
const Uint32 FlagsGrabbedWindowed = SDL_WINDOW_INPUT_GRABBED;
const Uint32 FlagsGrabbedFullscreen = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_FULLSCREEN;
const Uint32 FlagsGrabbedDesktop = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_FULLSCREEN_DESKTOP;
const Uint32 FlagsGrabbedFocusedWindowed = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS;
const Uint32 FlagsGrabbedFocusedFullscreen = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_FULLSCREEN;
const Uint32 FlagsGrabbedFocusedDesktop = SDL_WINDOW_INPUT_GRABBED |
SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS |
SDL_WINDOW_FULLSCREEN_DESKTOP;

int main(int, char * []) {
SDL_Init(SDL_INIT_VIDEO);
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

#ifndef MY_WIDTH
    #define MY_WIDTH 1920
#endif

#ifndef MY_HEIGHT
    #define MY_HEIGHT 1200
#endif

#ifndef MY_FLAGS
    #define MY_FLAGS FlagsWindowed
#endif

SDL_Window * window = SDL_CreateWindow("Meow", SDL_WINDOWPOS_CENTERED,

SDL_WINDOWPOS_CENTERED, MY_WIDTH, MY_HEIGHT, SDL_WINDOW_OPENGL | MY_FLAGS);
SDL_GLContext context = SDL_GL_CreateContext(window);
bool changing = true;
const Uint64 freq = SDL_GetPerformanceFrequency();

for (bool keep_going = true; keep_going; ) {
    for (SDL_Event event; SDL_PollEvent(&event); ) {
        switch (event.type) {
            case SDL_KEYDOWN:
            case SDL_QUIT:
                keep_going = false;
                break;
            case SDL_MOUSEBUTTONUP:
                changing = !changing;
                break;
            default:
                break;
        }
    }

    if (changing) {
        const double d = (SDL_GetPerformanceCounter() % freq) * 1.0 /

freq;
glClearColor(d, d, d, 1.0);
}

    glClear(GL_COLOR_BUFFER_BIT);
    SDL_GL_SwapWindow(window);
}

SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;

}

I have provided the Flags* constants and MY_* macros for convenience, so
you
can build the test case with varying command lines like:

g++ -Wall -Wextra -mthreads -mwindows meow.cpp -o meow.exe -lopengl32
-lSDL2
-limm32 -lole32 -loleaut32 -luuid -lversion -lwinmm -lmingw32 -lSDL2main
-DMY_FLAGS=FlagsGrabbedDesktop

instead of repeatedly altering the file.

Thanks,
Stephan T. Lavavej


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

[Sam Lantinga]

This is a great bug report. ?Can you submit it to bugzilla along with your
test program?

Done, tagged with target-2.0.0:
http://bugzilla.libsdl.org/show_bug.cgi?id=1966

Thanks,
STL

Thanks!On Sat, Jul 13, 2013 at 12:42 AM, Stephan T. Lavavej wrote:

[Sam Lantinga]

This is a great bug report. Can you submit it to bugzilla along with
your
test program?

Done, tagged with target-2.0.0:
http://bugzilla.libsdl.org/show_bug.cgi?id=1966

Thanks,
STL


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org