Allocate displays as an array of pointers instead of an array of objects

This fixes current_mode from pointing at the wrong data when displays are moved around
main
Sam Lantinga 2023-08-01 18:48:35 -07:00
parent 07578fde3d
commit 68a4bb01e0
14 changed files with 79 additions and 85 deletions

View File

@ -363,7 +363,7 @@ struct SDL_VideoDevice
SDL_Window *wakeup_window;
SDL_Mutex *wakeup_lock; /* Initialized only if WaitEventTimeout/SendWakeupEvent are supported */
int num_displays;
SDL_VideoDisplay *displays;
SDL_VideoDisplay **displays;
SDL_Window *windows;
SDL_Window *grabbed_window;
Uint8 window_magic;

View File

@ -642,57 +642,51 @@ SDL_DisplayID SDL_AddBasicVideoDisplay(const SDL_DisplayMode *desktop_mode)
SDL_DisplayID SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send_event)
{
SDL_VideoDisplay *displays, *new_display;
SDL_DisplayID id = 0;
SDL_VideoDisplay **displays, *new_display;
SDL_DisplayID id;
int i;
displays = (SDL_VideoDisplay *)SDL_malloc((_this->num_displays + 1) * sizeof(*displays));
if (displays) {
int i;
if (_this->displays) {
/* The display list may contain self-referential pointers to the desktop mode. */
SDL_memcpy(displays, _this->displays, _this->num_displays * sizeof(*displays));
for (i = 0; i < _this->num_displays; ++i) {
if (displays[i].current_mode == &_this->displays[i].desktop_mode) {
displays[i].current_mode = &displays[i].desktop_mode;
}
}
SDL_free(_this->displays);
}
_this->displays = displays;
id = _this->next_object_id++;
new_display = &displays[_this->num_displays++];
SDL_memcpy(new_display, display, sizeof(*new_display));
new_display->id = id;
new_display->device = _this;
if (display->name) {
new_display->name = SDL_strdup(display->name);
} else {
char name[32];
SDL_itoa(id, name, 10);
new_display->name = SDL_strdup(name);
}
if (new_display->content_scale == 0.0f) {
new_display->content_scale = 1.0f;
}
new_display->desktop_mode.displayID = id;
new_display->current_mode = &new_display->desktop_mode;
SDL_FinalizeDisplayMode(&new_display->desktop_mode);
for (i = 0; i < new_display->num_fullscreen_modes; ++i) {
new_display->fullscreen_modes[i].displayID = id;
}
if (send_event) {
SDL_SendDisplayEvent(new_display, SDL_EVENT_DISPLAY_CONNECTED, 0);
}
} else {
new_display = (SDL_VideoDisplay *)SDL_malloc(sizeof(*new_display));
if (!new_display) {
SDL_OutOfMemory();
return 0;
}
displays = (SDL_VideoDisplay **)SDL_realloc(_this->displays, (_this->num_displays + 1) * sizeof(*displays));
if (!displays) {
SDL_OutOfMemory();
SDL_free(new_display);
return 0;
}
_this->displays = displays;
_this->displays[_this->num_displays++] = new_display;
id = _this->next_object_id++;
SDL_memcpy(new_display, display, sizeof(*new_display));
new_display->id = id;
new_display->device = _this;
if (display->name) {
new_display->name = SDL_strdup(display->name);
} else {
char name[32];
SDL_itoa(id, name, 10);
new_display->name = SDL_strdup(name);
}
if (new_display->content_scale == 0.0f) {
new_display->content_scale = 1.0f;
}
new_display->desktop_mode.displayID = id;
new_display->current_mode = &new_display->desktop_mode;
SDL_FinalizeDisplayMode(&new_display->desktop_mode);
for (i = 0; i < new_display->num_fullscreen_modes; ++i) {
new_display->fullscreen_modes[i].displayID = id;
}
if (send_event) {
SDL_SendDisplayEvent(new_display, SDL_EVENT_DISPLAY_CONNECTED, 0);
}
return id;
}
@ -715,7 +709,7 @@ void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event)
return;
}
display = &_this->displays[display_index];
display = _this->displays[display_index];
if (send_event) {
SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_DISCONNECTED, 0);
@ -727,6 +721,7 @@ void SDL_DelVideoDisplay(SDL_DisplayID displayID, SDL_bool send_event)
display->desktop_mode.driverdata = NULL;
SDL_free(display->driverdata);
display->driverdata = NULL;
SDL_free(display);
if (display_index < (_this->num_displays - 1)) {
SDL_memmove(&_this->displays[display_index], &_this->displays[display_index + 1], (_this->num_displays - display_index - 1) * sizeof(_this->displays[display_index]));
@ -755,7 +750,7 @@ SDL_DisplayID *SDL_GetDisplays(int *count)
}
for (i = 0; i < _this->num_displays; ++i) {
displays[i] = _this->displays[i].id;
displays[i] = _this->displays[i]->id;
}
displays[i] = 0;
} else {
@ -776,7 +771,7 @@ SDL_VideoDisplay *SDL_GetVideoDisplay(SDL_DisplayID displayID)
if (display_index < 0) {
return NULL;
}
return &_this->displays[display_index];
return _this->displays[display_index];
}
SDL_VideoDisplay *SDL_GetVideoDisplayForWindow(SDL_Window *window)
@ -790,7 +785,7 @@ SDL_DisplayID SDL_GetPrimaryDisplay(void)
SDL_UninitializedVideo();
return 0;
}
return _this->displays[0].id;
return _this->displays[0]->id;
}
int SDL_GetDisplayIndex(SDL_DisplayID displayID)
@ -802,7 +797,7 @@ int SDL_GetDisplayIndex(SDL_DisplayID displayID)
}
for (display_index = 0; display_index < _this->num_displays; ++display_index) {
if (displayID == _this->displays[display_index].id) {
if (displayID == _this->displays[display_index]->id) {
return display_index;
}
}
@ -853,7 +848,7 @@ int SDL_GetDisplayBounds(SDL_DisplayID displayID, SDL_Rect *rect)
rect->x = 0;
rect->y = 0;
} else {
SDL_GetDisplayBounds(_this->displays[SDL_GetDisplayIndex(displayID) - 1].id, rect);
SDL_GetDisplayBounds(_this->displays[SDL_GetDisplayIndex(displayID) - 1]->id, rect);
rect->x += rect->w;
}
rect->w = display->current_mode->w;
@ -1256,7 +1251,7 @@ static SDL_DisplayID GetDisplayForRect(int x, int y, int w, int h)
if (_this) {
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
SDL_Rect display_rect;
SDL_GetDisplayBounds(display->id, &display_rect);
@ -1390,14 +1385,14 @@ static void SDL_CheckWindowDisplayChanged(SDL_Window *window)
/* Sanity check our fullscreen windows */
display_index = SDL_GetDisplayIndex(displayID);
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
if (display->fullscreen_window == window) {
if (display_index != i) {
if (display_index < 0) {
display_index = i;
} else {
SDL_VideoDisplay *new_display = &_this->displays[display_index];
SDL_VideoDisplay *new_display = _this->displays[display_index];
/* The window was moved to a different display */
if (new_display->fullscreen_window &&
@ -1489,7 +1484,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen)
}
} else {
for (i = 0; i < _this->num_displays; ++i) {
display = &_this->displays[i];
display = _this->displays[i];
if (display->fullscreen_window == window) {
break;
}
@ -1528,7 +1523,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen)
}
} else if (fullscreen && window->last_fullscreen_exclusive_display && !window->fullscreen_exclusive) {
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *last_display = &_this->displays[i];
SDL_VideoDisplay *last_display = _this->displays[i];
if (last_display->fullscreen_window == window) {
SDL_SetDisplayModeForDisplay(last_display, NULL);
if (_this->SetWindowFullscreen) {
@ -1584,7 +1579,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen)
/* Restore the video mode on other displays if needed */
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *other = &_this->displays[i];
SDL_VideoDisplay *other = _this->displays[i];
if (other != display && other->fullscreen_window == window) {
SDL_SetDisplayModeForDisplay(other, NULL);
if (_this->SetWindowFullscreen) {
@ -3733,7 +3728,7 @@ void SDL_VideoQuit(void)
_this->VideoQuit(_this);
for (i = _this->num_displays; i--; ) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
SDL_DelVideoDisplay(display->id, SDL_FALSE);
}
if (_this->displays) {

View File

@ -268,7 +268,7 @@ void Android_SendResize(SDL_Window *window)
*/
SDL_VideoDevice *device = SDL_GetVideoDevice();
if (device && device->num_displays > 0) {
SDL_VideoDisplay *display = &device->displays[0];
SDL_VideoDisplay *display = device->displays[0];
SDL_DisplayMode desktop_mode;
SDL_zero(desktop_mode);

View File

@ -255,7 +255,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
SDL_Window *window = device->windows;
int i;
for (i = 0; i < device->num_displays; ++i) {
SDL_Window *fullscreen_window = device->displays[i].fullscreen_window;
SDL_Window *fullscreen_window = device->displays[i]->fullscreen_window;
if (fullscreen_window) {
if (fullscreen_window->flags & SDL_WINDOW_MINIMIZED) {
SDL_RestoreWindow(fullscreen_window);

View File

@ -520,7 +520,7 @@ void Cocoa_QuitModes(SDL_VideoDevice *_this)
int i, j;
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
SDL_DisplayModeData *mode;
if (display->current_mode->driverdata != display->desktop_mode.driverdata) {

View File

@ -2467,9 +2467,9 @@ SDL_DisplayID Cocoa_GetDisplayForWindow(SDL_VideoDevice *_this, SDL_Window *wind
displayid = [[screen.deviceDescription objectForKey:@"NSScreenNumber"] unsignedIntValue];
for (i = 0; i < _this->num_displays; i++) {
SDL_DisplayData *displaydata = _this->displays[i].driverdata;
SDL_DisplayData *displaydata = _this->displays[i]->driverdata;
if (displaydata != NULL && displaydata->display == displayid) {
return _this->displays[i].id;
return _this->displays[i]->id;
}
}
}

View File

@ -48,7 +48,6 @@ struct SDL_DisplayData
static void N3DS_DeleteDevice(SDL_VideoDevice *device)
{
SDL_free(device->displays);
SDL_free(device->driverdata);
SDL_free(device);
}

View File

@ -392,7 +392,7 @@ void UIKit_QuitModes(SDL_VideoDevice *_this)
int i, j;
@autoreleasepool {
for (i = 0; i < _this->num_displays; i++) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
UIKit_FreeDisplayModeData(&display->desktop_mode);
for (j = 0; j < display->num_fullscreen_modes; j++) {

View File

@ -935,7 +935,7 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
Wayland_FiniMouse(data);
for (i = _this->num_displays - 1; i >= 0; --i) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
Wayland_free_display(display);
}

View File

@ -2154,7 +2154,7 @@ int Wayland_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window)
if (window->flags & SDL_WINDOW_HIGH_PIXEL_DENSITY) {
int i;
for (i = 0; i < _this->num_displays; i++) {
float scale = _this->displays[i].driverdata->scale_factor;
float scale = _this->displays[i]->driverdata->scale_factor;
data->windowed_scale_factor = SDL_max(data->windowed_scale_factor, scale);
}
}

View File

@ -352,7 +352,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
// ready to be added to allow any displays that we can't fully query to be
// removed
for (i = 0; i < _this->num_displays; ++i) {
SDL_DisplayData *driverdata = _this->displays[i].driverdata;
SDL_DisplayData *driverdata = _this->displays[i]->driverdata;
if (SDL_wcscmp(driverdata->DeviceName, info->szDevice) == 0) {
SDL_bool moved = (index != i);
SDL_bool changed_bounds = SDL_FALSE;
@ -368,11 +368,11 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
}
if (moved) {
SDL_VideoDisplay tmp;
SDL_VideoDisplay *tmp;
SDL_memcpy(&tmp, &_this->displays[index], sizeof(tmp));
SDL_memcpy(&_this->displays[index], &_this->displays[i], sizeof(tmp));
SDL_memcpy(&_this->displays[i], &tmp, sizeof(tmp));
tmp = _this->displays[index];
_this->displays[index] = _this->displays[i];
_this->displays[i] = tmp;
i = index;
}
@ -380,7 +380,7 @@ static void WIN_AddDisplay(SDL_VideoDevice *_this, HMONITOR hMonitor, const MONI
driverdata->state = DisplayUnchanged;
if (!_this->setting_display_mode) {
SDL_VideoDisplay *existing_display = &_this->displays[i];
SDL_VideoDisplay *existing_display = _this->displays[i];
SDL_Rect bounds;
SDL_ResetFullscreenDisplayModes(existing_display);
@ -654,7 +654,7 @@ void WIN_RefreshDisplays(SDL_VideoDevice *_this)
// Mark all displays as potentially invalid to detect
// entries that have actually been removed
for (i = 0; i < _this->num_displays; ++i) {
SDL_DisplayData *driverdata = _this->displays[i].driverdata;
SDL_DisplayData *driverdata = _this->displays[i]->driverdata;
driverdata->state = DisplayRemoved;
}
@ -665,7 +665,7 @@ void WIN_RefreshDisplays(SDL_VideoDevice *_this)
// Delete any entries still marked as invalid, iterate
// in reverse as each delete takes effect immediately
for (i = _this->num_displays - 1; i >= 0; --i) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
SDL_DisplayData *driverdata = display->driverdata;
if (driverdata->state == DisplayRemoved) {
SDL_DelVideoDisplay(display->id, SDL_TRUE);
@ -674,7 +674,7 @@ void WIN_RefreshDisplays(SDL_VideoDevice *_this)
// Send events for any newly added displays
for (i = 0; i < _this->num_displays; ++i) {
SDL_VideoDisplay *display = &_this->displays[i];
SDL_VideoDisplay *display = _this->displays[i];
SDL_DisplayData *driverdata = display->driverdata;
if (driverdata->state == DisplayAdded) {
SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_CONNECTED, 0);

View File

@ -467,8 +467,8 @@ static int X11_MessageBoxCreateWindow(SDL_MessageBoxDataX11 *data)
X11_XTranslateCoordinates(display, windowdata->xwindow, RootWindow(display, data->screen), x, y, &x, &y, &dummy);
} else {
const SDL_VideoDevice *dev = SDL_GetVideoDevice();
if ((dev) && (dev->displays) && (dev->num_displays > 0)) {
const SDL_VideoDisplay *dpy = &dev->displays[0];
if (dev && dev->displays && dev->num_displays > 0) {
const SDL_VideoDisplay *dpy = dev->displays[0];
const SDL_DisplayData *dpydata = dpy->driverdata;
x = dpydata->x + ((dpy->current_mode->w - data->dialog_width) / 2);
y = dpydata->y + ((dpy->current_mode->h - data->dialog_height) / 3);

View File

@ -99,7 +99,7 @@ static void UpdateDisplayContentScale(float scale)
if (viddevice) {
for (i = 0; i < viddevice->num_displays; ++i) {
SDL_SetDisplayContentScale(&viddevice->displays[i], scale);
SDL_SetDisplayContentScale(viddevice->displays[i], scale);
}
}
}

View File

@ -84,7 +84,7 @@ static int X11_SafetyNetErrHandler(Display *d, XErrorEvent *e)
if (device != NULL) {
int i;
for (i = 0; i < device->num_displays; i++) {
SDL_VideoDisplay *display = &device->displays[i];
SDL_VideoDisplay *display = device->displays[i];
if (SDL_GetCurrentDisplayMode(display->id) != SDL_GetDesktopDisplayMode(display->id)) {
X11_SetDisplayMode(device, display, &display->desktop_mode);
}