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 4540

Summary: Setting window to fullscreen on a monitor (SDL_WINDOW_FULLSCREEN) other than the primary will inevitably move the window back to primary monitor.
Product: SDL Reporter: Darrell <salads.games+sdl2>
Component: videoAssignee: Ryan C. Gordon <icculus>
Status: ASSIGNED --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 Keywords: target-2.0.16
Version: 2.0.9   
Hardware: x86_64   
OS: Windows 10   
Attachments: work in progress patch
second attempt at migrating to a new display

Description Darrell 2019-03-07 05:12:56 UTC
Hello, I’m trying to see if can get SDL2 to go fullscreen with a video mode change (SDL_WINDOW_FULLSCREEN) on other monitors than that of my primary monitor.

However, when I call SDL_SetWindowFullscreen after moving the window to another monitor, it will seemingly set it’s size, video mode, and position correctly but then will move the window back to the primary monitor, while keeping the video mode of the desired monitor, making both monitors have the same video mode while showing the window on the wrong monitor.

I’ve made a test app solely for the purpose of figuring this out, found here: https://github.com/Salads/SDL2-WindowMode-Test/blob/master/Source/Main.cpp (uses ImGui + imgui_sdl)

Running with the debug build of SDL2, I verified that SDL_SetWindowFullscreen works (if I first set it to windowed mode and set the position and size to that of another monitor) but when ImGuiSDL::Render(ImGui::GetDrawData()); is called, it switches the window back to the primary monitor. Internally, ImGuiSDL uses SDL_RenderFillRect, here’s a pseudo stack trace from there:

SDL_RenderFillRect
D3D_ActivateRenderer
D3D_Reset
IDirect3DDevice9_Reset - Window moves back to primary monitor here at render\direct3d\SDL_render_d3d.c:355

This also happens on another app that uses SDL2 as well, where it simply gets the system window handle and uses that to go on and initialize directX. I can try to see if the stack trace is somewhat similar on the other app since it takes another approach to using SDL2.
Comment 1 Darrell 2019-03-07 08:37:58 UTC
Tracing through the other app I mentioned, I found that it also has the window move back to the primary monitor when the D3D9Device is reset, so this may have something to do with how DirectX works...?
Comment 2 Ryan C. Gordon 2019-07-30 17:49:36 UTC
(Sorry if you get several emails like this, we're marking a bunch of bugs.)

We're hoping to ship SDL 2.0.11 on a much shorter timeframe than we have historically done releases, so I'm starting to tag bugs we hope to have closed in this release cycle.

Note that this tag means we just intend to scrutinize this bug for the 2.0.11 release: we may fix it, reject it, or even push it back to a later release for now, but this helps give us both a goal and a wishlist for the next release.

If this bug has been quiet for a few months and you have new information (such as, "this is definitely still broken" or "this got fixed at some point"), please feel free to retest and/or add more notes to the bug.

--ryan.
Comment 3 Ryan C. Gordon 2019-09-20 20:47:38 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.
Comment 4 Ryan C. Gordon 2019-09-20 20:48:40 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.
Comment 5 Sam Lantinga 2020-02-11 17:49:58 UTC
Ryan, do you have a multi-monitor setup to debug this?
Comment 6 Ryan C. Gordon 2020-02-11 18:48:12 UTC
(In reply to Sam Lantinga from comment #5)
> Ryan, do you have a multi-monitor setup to debug this?

I do, I'm looking at this one right now.

--ryan.
Comment 7 Sam Lantinga 2020-02-11 18:49:44 UTC
I think the D3D device instance has a handle to the monitor, so we may need to update that when the window position changes.
Comment 8 Ryan C. Gordon 2020-02-11 19:43:09 UTC
The imgui test app in this bug is kinda awesome.  :)    I can reproduce it here, working on tracking it down.

--ryan.
Comment 9 Ryan C. Gordon 2020-02-11 20:18:11 UTC
(In reply to Sam Lantinga from comment #7)
> I think the D3D device instance has a handle to the monitor, so we may need
> to update that when the window position changes.

You are probably correct; during SDL_RenderPresent, after the fullscreen change, D3D_RunCommandQueue tries to activate its stuff at the start, which calls D3D_Reset to trash everything and rebuild it due to the window change.

In there, IDirect3DDevice9_Reset() gets called, and before that call returns the window is back on the primary display.

I'll read up and figure it out, but this is creeping towards being solved now.

--ryan.
Comment 10 Ryan C. Gordon 2020-02-11 22:38:25 UTC
I’m guessing it’s because IDirect3DDevice9_CreateDevice has to specify a display adapter and Reset doesn’t let you choose a different one. We probably have to fully tear down And rebuild the D3D device in this scenario if this is the culprit.

(Obviously the window can safely drag between displays or be moved there programmatically, it’s just the fullscreening causing a problem here.)

--ryan.
Comment 11 Sam Lantinga 2020-02-12 00:33:47 UTC
Yup, that's probably true. If we go fullscreen on a different display than we started with, we need to recreate the D3D device on that display.

Let's go ahead and fix this after 2.0.12 is out.
Comment 12 Ryan C. Gordon 2020-02-12 01:48:07 UTC
(In reply to Sam Lantinga from comment #11)
> Yup, that's probably true. If we go fullscreen on a different display than
> we started with, we need to recreate the D3D device on that display.
> 
> Let's go ahead and fix this after 2.0.12 is out.

Wait, I’m mostly there, just have to move some code from D3D_CreateRenderer to a separate function.

--ryan.
Comment 13 Ryan C. Gordon 2020-02-12 05:36:37 UTC
Created attachment 4205 [details]
work in progress patch

> Wait, I’m mostly there, just have to move some code from D3D_CreateRenderer
> to a separate function.

Okay, nevermind, this patch is pretty big and still not right (among other things, we lose all the textures when the device is recreated), but I'll post the work-in-progress here for when we revisit.

--ryan.
Comment 14 Ryan C. Gordon 2020-04-07 04:06:43 UTC
Created attachment 4296 [details]
second attempt at migrating to a new display

(In reply to Ryan C. Gordon from comment #13)
> Okay, nevermind, this patch is pretty big and still not right (among other
> things, we lose all the textures when the device is recreated), but I'll
> post the work-in-progress here for when we revisit.

Been fighting with this all week, and now I can move this program to a different display and keep the textures, by saving them all off before destroying everything and recreating new textures on the new device with the saved-off data. This adds some complexity, but as a side-benefit, we don't even have to send an SDL_RENDER_TARGETS_RESET event in this case.

I'm attaching the current work-in-progress, because I have to take a break from this. It's still a little crashy, so it isn't ready for revision control, but this actually _almost_ works now.

We'll have to decide if all this heavy-lifting is worth it, though. Now that I can see what's involved, I'm a little nervous about it. It's cool when it works, but I'm still not sure we shouldn't have just refused the fullscreen request in the first place.

--ryan.