Recent

Author Topic: [SOLVED] SDL2 — two screens, two windows and SDL_SetWindowGrab problem  (Read 2114 times)

furious programming

  • Hero Member
  • *****
  • Posts: 853
I'm working on my new video game project, in which I want to support ”split screen” in the form of splitting the game into two independent windows (one game process with two windows), if the player have PC with two monitors or one monitor and TV. I have no problems with handling two windows, also no problem with handling exclusive video mode for one window. Both cannot be run in exclusive video mode, so the solution is to create one window in exclusive video mode and second in desktop fullscreen.

When the main window is displayed on main monitor, I can use SDL_SetWindowGrab — mouse position is limited to window/screen area. If I have two windows, when main window use exclusive wideo mode on main screen and second window use desktop fullscreen on secondary monitor, I can use SDL_SetWindowGrab for main window — works perfectly. But if I would like to set grabbing for secondary window, it doesn't work — I can move cursor between both screens.

I know that the description above looks complicated, so below are samples to illustrate what is going on.

Code: Pascal  [Select][+][-]
  1. // one window, shown on main screen in 800x600 exclusive video mode
  2. // mouse is grabbed properly
  3.  
  4. SDL_GetDisplayMode(0, 5, @Mode);  // 5th mode means 800x600 (on my computer)
  5. SDL_GetDisplayBounds(0, @Bounds); // bounds of the main screen
  6.  
  7. Window1 := SDL_CreateWindow('Main', Bounds.X, Bounds.Y, Mode.W, Mode.H, SDL_WINDOW_FULLSCREEN);
  8. Renderer1 := SDL_CreateRenderer(Window1, 0, SDL_RENDERER_ACCELERATED);
  9.  
  10. SDL_SetWindowGrab(Window1, SDL_TRUE);

Code: Pascal  [Select][+][-]
  1. // one window, shown on secondary screen in 800x600 exclusive video mode
  2. // mouse is grabbed properly
  3.  
  4. SDL_GetDisplayMode(1, 13, @Mode); // 13th mode means 800x600 (on my computer)
  5. SDL_GetDisplayBounds(1, @Bounds); // bounds of the secondary screen
  6.  
  7. Window1 := SDL_CreateWindow('Main', Bounds.X, Bounds.Y, Mode.W, Mode.H, SDL_WINDOW_FULLSCREEN);
  8. Renderer1 := SDL_CreateRenderer(Window1, 0, SDL_RENDERER_ACCELERATED);
  9.  
  10. SDL_SetWindowGrab(Window1, SDL_TRUE);

Code: Pascal  [Select][+][-]
  1. // two windows:
  2. //   - 1st shown on main screen in 800x600 exclusive video mode
  3. //   - 2nd shown on secondary screen in desktop fullscreen mode
  4. // mouse is grabbed properly (in the main window on main screen)
  5.  
  6. SDL_GetDisplayMode(0, 5, @Mode);  // 5th mode means 800x600 (on my computer)
  7. SDL_GetDisplayBounds(0, @Bounds); // bounds of the main screen
  8.  
  9. Window1 := SDL_CreateWindow('Main', Bounds.X, Bounds.Y, Mode.W, Mode.H, SDL_WINDOW_FULLSCREEN);
  10. Renderer1 := SDL_CreateRenderer(Window1, 0, SDL_RENDERER_ACCELERATED);
  11.  
  12. SDL_GetCurrentDisplayMode(1, @Mode); // current resolution of secondary screen
  13. SDL_GetDisplayBounds(1, @Bounds);    // current bounds of secondary screen
  14.  
  15. Window2 := SDL_CreateWindow('Side', Bounds.X, Bounds.Y, Mode.W, Mode.H, SDL_WINDOW_FULLSCREEN_DESKTOP or SDL_WINDOW_ALWAYS_ON_TOP or SDL_WINDOW_SKIP_TASKBAR);
  16. Renderer2 := SDL_CreateRenderer(Window2, 0, SDL_RENDERER_ACCELERATED);
  17.  
  18. SDL_SetWindowGrab(Window1, SDL_TRUE);

Code: Pascal  [Select][+][-]
  1. // two windows:
  2. //   - 1st shown on main screen in desktop fullscreen mode
  3. //   - 2nd shown on secondary screen in 800x600 exclusive video mode
  4. // mouse is not grabbed in the secondary window (shown on secondary screen)
  5.  
  6. SDL_GetCurrentDisplayMode(0, @Mode); // current resolution of main screen
  7. SDL_GetDisplayBounds(0, @Bounds);    // current bounds of main screen
  8.  
  9. Window1 := SDL_CreateWindow('Main', Bounds.X, Bounds.Y, Mode.W, Mode.H, SDL_WINDOW_FULLSCREEN_DESKTOP or SDL_WINDOW_ALWAYS_ON_TOP or SDL_WINDOW_SKIP_TASKBAR);
  10. Renderer1 := SDL_CreateRenderer(Window1, 0, SDL_RENDERER_ACCELERATED);
  11.  
  12. SDL_GetDisplayMode(1, 13, @Mode); // 13th mode means 800x600 (on my computer)
  13. SDL_GetDisplayBounds(1, @Bounds); // bounds of the secondary screen
  14.  
  15. Window2 := SDL_CreateWindow('Side', Bounds.X, Bounds.Y, Mode.W, Mode.H, SDL_WINDOW_FULLSCREEN);
  16. Renderer2 := SDL_CreateRenderer(Window2, 0, SDL_RENDERER_ACCELERATED);
  17.  
  18. SDL_SetWindowGrab(Window2, SDL_TRUE);  // does not work

The last example properly set the exclusive video mode and custom resolution on the secondary monitor and shows main window on the main screen in desktop fullscreen, but mouse is not limited to the bounds of secondary monitor. It does not matter if the exclusive video mode is enabled or not, because if I create both windows using desktop fullscreen, still I cannot set grabbing in secondary window.

It appears that SDL_SetWindowGrab is limited or has a bug. Grabbing mouse in window that is displayed on secondary screen (when there are two windows) is imposible. Anyone can confirm this behavior?

I'm interested mainly on Windows 7-11 (64 bit) solution, because this platform is the only target for my game (for now). I'm using SDL headers from the PascalGameDevelopment/SDL2-for-Pascal repository and the SDL 2.0.20 dll file (this is the latest version).
« Last Edit: May 15, 2022, 02:34:22 am by furious programming »
Lazarus 3.2 with FPC 3.2.2, Windows 10 — all 64-bit

Working solo on an acrade, action/adventure game in retro style (pixelart), programming the engine and shell from scratch, using Free Pascal and SDL. Release planned in 2026.

metis

  • Sr. Member
  • ****
  • Posts: 300
« Last Edit: January 31, 2023, 08:06:32 pm by metis »
Life could be so easy, if there weren't those f*** Details.
My FFmpeg4Lazarus = FFPlay4Laz + FFGrab4Laz + FFInfo4Laz

 

TinyPortal © 2005-2018