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 4550

Summary: SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH broken sometimes, e.g. between two app-owned windows
Product: SDL Reporter: Ellie <etc0de>
Component: eventsAssignee: Sam Lantinga <slouken>
Status: RESOLVED INVALID QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2    
Version: 2.0.9   
Hardware: x86_64   
OS: Linux   

Description Ellie 2019-03-13 18:04:06 UTC
I have found SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH=1 to be quite unreliable which makes for a frustrating user experience, and I finally found a scenario where it reliably breaks:

On Linux, if you run the following test program at least under GNOME 3/Wayland, you will see that all clicks are LOST in an SDL2 program with two windows of which one is constantly raised, and given the click is on the currently UNFOCUSED window.

Steps to reproduce:
1. Compile test program
2. Launch. You should see two windows, the smaller one in foreground
3. Randomly click INTO each window in random orders. Once clicked both of the windows should ALWAYS toggle their color with each click. They DON'T.

Expected behavior:
Test program windows always toggle color

Actual behavior:
All clicks (and therefore color toggles) are lost if the window is currently not focused, exactly the opposite of what SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH set to 1 should do.


#include <SDL2/SDL.h>

int main(int argc, const char** argv) {
    // Initialize and make sure focus clickthrough is ENABLED:
    SDL_SetHintWithPriority(
        "SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH", "1",
        SDL_HINT_OVERRIDE
    );
    SDL_Init(SDL_INIT_VIDEO);

    // Create two windows to play with:
    SDL_Window *bg_window = SDL_CreateWindow(
        "background window",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        500, 500,
        0 // FLAGS
    );
    int bg_window_is_colored = 0;
    SDL_Window *fg_window = SDL_CreateWindow(
        "foreground window",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        200, 200,
        0 // FLAGS
    );
    int fg_window_is_colored = 0;

    // Manage the two windows such that clicking them is VISIBLE
    // (by making them toggle the fill color on each click)
    SDL_Event e;
    int terminate = 0;
    while (!terminate) {
        while (SDL_PollEvent(&e) != 0) {
            if (e.type == SDL_MOUSEBUTTONDOWN) {
                // When clicking any window, swap the colored state:
                int windowID = e.button.windowID;
                if (windowID == SDL_GetWindowID(bg_window))
                    bg_window_is_colored = !bg_window_is_colored;
                else if (windowID == SDL_GetWindowID(fg_window))
                    fg_window_is_colored = !fg_window_is_colored;

                // If clicking the background window, raise fg window:
                if (windowID == SDL_GetWindowID(bg_window))
                    SDL_RaiseWindow(fg_window);
            } else if (e.type == SDL_WINDOWEVENT) {
                if (e.window.event == SDL_WINDOWEVENT_CLOSE) {
                    terminate = 1;
                    break;
                } else if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
                    int windowID = e.window.windowID;
                    if (windowID == SDL_GetWindowID(bg_window))
                        SDL_RaiseWindow(fg_window);
                }
            } else if (e.type == SDL_QUIT) {
                break;
            }
        }
        if (terminate) break;

        // Fill background window with color:
        SDL_Surface *bg_window_surface = SDL_GetWindowSurface(bg_window);
        if (bg_window_is_colored)
            SDL_FillRect(bg_window_surface, NULL,
                         SDL_MapRGB(bg_window_surface->format, 255, 0, 0));
        else
            SDL_FillRect(bg_window_surface, NULL,
                         SDL_MapRGB(bg_window_surface->format, 0, 0, 0));
        SDL_UpdateWindowSurface(bg_window);
        // Fill foreground window with color:
        SDL_Surface *fg_window_surface = SDL_GetWindowSurface(fg_window);
        if (fg_window_is_colored)
            SDL_FillRect(fg_window_surface, NULL,
                         SDL_MapRGB(fg_window_surface->format, 255, 0, 0));
        else
            SDL_FillRect(fg_window_surface, NULL,
                         SDL_MapRGB(fg_window_surface->format, 0, 0, 0));
        SDL_UpdateWindowSurface(fg_window);
    }
}
Comment 1 Ellie 2019-04-04 13:56:23 UTC
I set the hint wrong, didn't I? Since I used "SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH" instead of SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH... (which is "SDL_MOUSE_FOCUS_CLICKTHROUGH, a different value)

I just tried with the correct value and it appears to work fine, so this was just me being silly, apparently :-)