3

I am writing a program that displays an animation that is dependent on the size of the display. In order to get this to work with multiple displays, I have an array of display_data objects:

struct window_data
{
    SDL_Rect bounds;
    SDL_Window *window;
};

and initialize these for each display:

int numdisplays = SDL_GetNumVideoDisplays();
std::vector< window_data > screens( numdisplays );
for( int i = 0 ; i < numdisplays ; ++i )
{
    SDL_GetDisplayBounds( i, &( screens[ i ].bounds ) );
    screens[ i ].window
        = SDL_CreateWindow( "Display", screens[ i ].bounds.x,
                            screens[ i ].bounds.y, screens[ i ].bounds.w,
                            screens[ i ].bounds.h, SDL_WINDOW_FULLSCREEN );
}

This works fine as long as my mouse cursor is in the primary display, but if I start the program with the cursor in the secondary display, it will draw both windows in the secondary display, resulting in only the second window being visible. This behavior seems to depend only on the location of the cursor and not the terminal window from which I run the program.

I have verified that the same display numbers and bounds are found regardless of the cursor location, so I am perplexed by the variation in the program behavior. Is this the intended behavior of SDL2, or a bug? In either case, could anyone suggest a workaround?

EDIT: The mouse dependency shows up on Debian with XFCE. I have tried this on Windows as well and it outputs both windows on the second monitor, regardless of the mouse position.

trm
  • 410
  • 3
  • 10
  • How about first starting the first window and wait for the used to click it then start the second. – this Sep 11 '13 at 00:30
  • Just to double-check, `SDL_GetNumVideoDisplays()` does in fact return `2` on your dual-head Linux box? [Back in the day](http://stackoverflow.com/questions/7927974/sdl-fake-fullscreen-mode-on-dual-monitor-setup-under-linux) there were some issues with the multi-monitor API. – genpfault Sep 18 '13 at 18:10
  • yep. number of displays: 2 window # 0 : x = 0 y = 0 w = 1280 h = 1024 window # 1 : x = 0 y = 1024 w = 1280 h = 800 – trm Sep 18 '13 at 23:40
  • What exact operating system and SDL version was this? On Ubuntu 18.04 with SDL 2.0.8 things seem to work okay. – Stéphane Gourichon Aug 05 '18 at 19:03

2 Answers2

1

Try SDL_WINDOW_BORDERLESS instead of SDL_WINDOW_FULLSCREEN.

I'm not sure if multiple fullscreen windows can meaningfully coexist, especially once you factor in input grabs.

Try something like this:

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

struct window_data
{
    SDL_Rect bounds;
    SDL_Window *window;
    SDL_Renderer* renderer;
};

int main( int argc, char **argv )
{
    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
        return EXIT_FAILURE;

    std::vector< window_data > screens( SDL_GetNumVideoDisplays() );
    for( size_t i = 0; i < screens.size(); ++i )
    {
        window_data& screen = screens[ i ];
        SDL_GetDisplayBounds( i, &screen.bounds );
        screen.window = SDL_CreateWindow
            ( 
            "Display", 
            screen.bounds.x, screen.bounds.y, 
            screen.bounds.w, screen.bounds.h, 
            SDL_WINDOW_BORDERLESS
            );
        screen.renderer = SDL_CreateRenderer( screen.window, 0, SDL_RENDERER_ACCELERATED );
        SDL_ShowWindow( screen.window );
    }

    bool running = true;
    while( running )
    {
        SDL_Event ev;
        while( SDL_PollEvent( &ev ) )
        {
            if( ev.type == SDL_QUIT )  running = false;
            if( ev.type == SDL_KEYUP &&
                ev.key.keysym.sym == SDLK_ESCAPE ) running = false;
        }

        for( size_t i = 0; i < screens.size(); ++i )
        {
            window_data& screen = screens[ i ];
            SDL_SetRenderDrawColor( screen.renderer, 255, 0, 0, 255 );
            SDL_RenderFillRect( screen.renderer, NULL );
            SDL_RenderPresent( screen.renderer );
        }

        SDL_Delay( 33 );
    }

    for( size_t i = 0; i < screens.size(); ++i )
    {
        window_data& screen = screens[ i ];
        SDL_DestroyRenderer( screen.renderer );
        SDL_DestroyWindow( screen.window );
    }

    SDL_Quit();

    return EXIT_SUCCESS;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
  • I tried SDL_WINDOW_BORDERLESS, but it shows the same result. I don't think the problem is having multiple full screen windows, but that the windows are only shown on the correct displays when the mouse pointer starts on display 0. I tried SDL_WINDOW_SHOWN at 1/2 of the display width and height, and the behavior is the same. – trm Sep 17 '13 at 21:25
  • That's...odd. The program I posted worked fine on my Win7 machine with two monitors. – genpfault Sep 17 '13 at 22:01
  • On Linux I have 2 red screens from this with the mouse on the first screen, but only the second screen is red when the mouse is there. I'll test it on Windows as soon as I get the chance, but if it works for you, it is probably an implementation bug. – trm Sep 18 '13 at 00:02
1

You can use the SDL_WINDOWPOS_UNDEFINED_DISPLAY macro in the position arguments to SDL_CreateWindow, in combination with the SDL_WINDOW_FULLSCREEN parameter.

Something like:

SDL_CreateWindow(
        "Window Name",
        SDL_WINDOWPOS_UNDEFINED_DISPLAY(display),
        SDL_WINDOWPOS_UNDEFINED_DISPLAY(display),
        0,
        0,
        SDL_WINDOW_FULLSCREEN),

The macro is not well documented, but you can see how is works clearly by reading the source code.

janm
  • 17,976
  • 1
  • 43
  • 61