Skip to content

Commit e5d6b89

Browse files
authored
Merge pull request #2992 from oddbookworm/linux-resize-fix
Fix break when the OS resizes our window in `set_mode`
2 parents 11317c6 + f387636 commit e5d6b89

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

src_c/display.c

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds)
827827
SDL_Surface *newownedsurf = NULL;
828828
int depth = 0;
829829
int flags = 0;
830-
int w, h;
830+
int w, h, w_actual, h_actual;
831831
PyObject *size = NULL;
832832
int vsync = SDL_FALSE;
833833
intptr_t hwnd = 0;
@@ -874,6 +874,9 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds)
874874
h = 0;
875875
}
876876

877+
h_actual = h;
878+
w_actual = w;
879+
877880
if (!SDL_WasInit(SDL_INIT_VIDEO)) {
878881
/* note SDL works special like this too */
879882
if (!pg_display_init(NULL, NULL))
@@ -1096,6 +1099,8 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds)
10961099
}
10971100
else {
10981101
win = SDL_CreateWindow(title, x, y, w_1, h_1, sdl_flags);
1102+
w_actual = w_1;
1103+
h_actual = h_1;
10991104
}
11001105
if (!win)
11011106
return RAISE(pgExc_SDLError, SDL_GetError());
@@ -1316,7 +1321,6 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds)
13161321

13171322
/* ensure window is always black after a set_mode call */
13181323
SDL_FillRect(surf, NULL, SDL_MapRGB(surf->format, 0, 0, 0));
1319-
pg_flip_internal(state);
13201324
}
13211325

13221326
/*set the window icon*/
@@ -1340,8 +1344,38 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds)
13401344
}
13411345
}
13421346

1343-
/*probably won't do much, but can't hurt, and might help*/
1347+
/*
1348+
* Can potentially yield a window resize event that forcibly changes
1349+
* the window size. This would invalidate the current surface we store,
1350+
* which can cause us to segfault in the event that we reference that
1351+
* surface later. So we need to flip, which forces us to update that
1352+
* surface as needed.
1353+
*/
13441354
SDL_PumpEvents();
1355+
pg_flip_internal(state);
1356+
1357+
/*
1358+
* Tell user if their requested screen size is ignored
1359+
* OpenGL, SCALED, and FULLSCREEN mess with the screensize in
1360+
* such a way that it can, at least our internal stuff, can
1361+
* be respected enough that we don't need to issue a warning
1362+
*/
1363+
if (!state->using_gl && ((flags & (PGS_SCALED | PGS_FULLSCREEN)) == 0) &&
1364+
!vsync) {
1365+
if (((surface->surf->w != w_actual) ||
1366+
(surface->surf->h != h_actual)) &&
1367+
((surface->surf->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0)) {
1368+
char buffer[150];
1369+
char *format_string =
1370+
"Requested window size was smaller than minimum supported "
1371+
"window size on platform. Using (%d, %d) instead.";
1372+
snprintf(buffer, sizeof(buffer), format_string, surface->surf->w,
1373+
surface->surf->h);
1374+
if (PyErr_WarnEx(PyExc_RuntimeWarning, buffer, 1) != 0) {
1375+
return NULL;
1376+
}
1377+
}
1378+
}
13451379

13461380
/*return the window's surface (screen)*/
13471381
Py_INCREF(surface);

test/display_test.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,11 @@ def test_get_init(self):
151151
self.assertTrue(display.get_init())
152152

153153
def test_get_surface(self):
154-
"""Ensures get_surface gets the current display surface."""
154+
"""Ensures get_surface gets the current display surface.
155+
We can't guarantee small screen sizes get respected, so the
156+
sizes of the surfaces returned from set_mode must be compared
157+
to the size of the surface from get_surface.
158+
"""
155159
lengths = (1, 5, 100)
156160
correct_depth = pygame.display.Info().bitsize
157161

@@ -169,7 +173,7 @@ def test_get_surface(self):
169173

170174
self.assertEqual(surface, expected_surface)
171175
self.assertIsInstance(surface, pygame.Surface)
172-
self.assertEqual(surface.get_size(), expected_size)
176+
self.assertEqual(surface.get_size(), expected_surface.get_size())
173177
self.assertEqual(surface.get_bitsize(), correct_depth)
174178

175179
def test_get_surface__mode_not_set(self):

0 commit comments

Comments
 (0)