+static void VID_ChangeDisplay_c(cvar_t *var)
+{
+ unsigned int fullscreenwanted, fullscreencurrent;
+ unsigned int displaywanted = bound(0, vid_display.integer, vid_info_displaycount.integer - 1);
+
+ if (!window)
+ return;
+
+ fullscreencurrent = SDL_GetWindowFlags(window) & (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
+ if (vid_fullscreen.integer)
+ fullscreenwanted = vid_desktopfullscreen.integer ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN;
+ else
+ fullscreenwanted = 0;
+
+ // moving to another display, changing the fullscreen mode or switching to windowed
+ if (vid.displayindex != displaywanted // SDL seems unable to move any fullscreen window to another display
+ || fullscreencurrent != fullscreenwanted) // even for desktop <-> exclusive: switching to windowed first feels safer
+ {
+ if (SDL_SetWindowFullscreen(window, 0) < 0)
+ {
+ Con_Printf(CON_ERROR "ERROR: can't deactivate fullscreen on display %i because %s\n", vid.displayindex, SDL_GetError());
+ return;
+ }
+ vid.fullscreen = false;
+ Con_DPrintf("Fullscreen deactivated on display %i\n", vid.displayindex);
+ }
+
+ // switching to windowed
+ if (!fullscreenwanted)
+ {
+ int toppx;
+ SDL_SetWindowSize(window, vid.width = vid_width.integer, vid.height = vid_height.integer);
+ SDL_SetWindowResizable(window, vid_resizable.integer ? SDL_TRUE : SDL_FALSE);
+ SDL_SetWindowBordered(window, (SDL_bool)!vid_borderless.integer);
+ SDL_GetWindowBordersSize(window, &toppx, NULL, NULL, NULL);
+ vid_wmborderless = !toppx;
+ if (vid_borderless.integer != vid_wmborderless) // this is not the state we're looking for
+ vid_wmborder_waiting = true;
+ }
+
+ // moving to another display or switching to windowed
+ if (vid.displayindex != displaywanted || !fullscreenwanted)
+ {
+// SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(displaywanted), SDL_WINDOWPOS_CENTERED_DISPLAY(displaywanted));
+// SDL_GetWindowPosition(window, &vid.xPos, &vid.yPos);
+
+ /* bones_was_here BUG: after SDL_DISPLAYEVENT hotplug events,
+ * SDL_WINDOWPOS_CENTERED_DISPLAY(displaywanted) may place the window somewhere completely invisible.
+ * WORKAROUND: manual positioning seems safer: although SDL_GetDisplayBounds() may return outdated values,
+ * SDL_SetWindowPosition() always placed the window somewhere fully visible, even if it wasn't correct,
+ * when tested with SDL 2.26.5.
+ */
+ SDL_Rect displaybounds;
+ if (SDL_GetDisplayBounds(displaywanted, &displaybounds) < 0)
+ {
+ Con_Printf(CON_ERROR "Error getting bounds of display %i: \"%s\"\n", displaywanted, SDL_GetError());
+ return;
+ }
+ vid.xPos = displaybounds.x + 0.5 * (displaybounds.w - vid.width);
+ vid.yPos = displaybounds.y + 0.5 * (displaybounds.h - vid.height);
+ SDL_SetWindowPosition(window, vid.xPos, vid.yPos);
+
+ vid.displayindex = displaywanted;
+ }
+
+ // switching to a fullscreen mode
+ if (fullscreenwanted)
+ {
+ if (SDL_SetWindowFullscreen(window, fullscreenwanted) < 0)
+ {
+ Con_Printf(CON_ERROR "ERROR: can't activate fullscreen on display %i because %s\n", vid.displayindex, SDL_GetError());
+ return;
+ }
+ // get the real framebuffer size in case the platform's screen coordinates are DPI scaled
+ SDL_GL_GetDrawableSize(window, &vid.width, &vid.height);
+ vid.fullscreen = true;
+ Con_DPrintf("Fullscreen activated on display %i\n", vid.displayindex);
+ }
+}
+