diff --git a/src_c/_pygame.h b/src_c/_pygame.h index c9d88a98b2..9e6ad78f1f 100644 --- a/src_c/_pygame.h +++ b/src_c/_pygame.h @@ -166,6 +166,8 @@ PG_GetSurfaceFormat(SDL_Surface *surf) #define PG_GetSurfaceClipRect SDL_GetSurfaceClipRect +#define PG_GL_SetSwapInterval SDL_GL_SetSwapInterval + #else /* ~SDL_VERSION_ATLEAST(3, 0, 0)*/ #define PG_ShowCursor() SDL_ShowCursor(SDL_ENABLE) #define PG_HideCursor() SDL_ShowCursor(SDL_DISABLE) @@ -378,6 +380,12 @@ PG_GetSurfaceClipRect(SDL_Surface *surface, SDL_Rect *rect) *rect = surface->clip_rect; return true; } + +static inline bool +PG_GL_SetSwapInterval(int interval) +{ + return SDL_GL_SetSwapInterval(interval) == 0; +} #endif /* DictProxy is useful for event posting with an arbitrary dict. Maintains diff --git a/src_c/display.c b/src_c/display.c index 959d29769c..622a02c19c 100644 --- a/src_c/display.c +++ b/src_c/display.c @@ -279,7 +279,11 @@ pg_get_init(PyObject *self, PyObject *_null) static PyObject * pg_get_active(PyObject *self, PyObject *_null) { - SDL_WindowFlags flags = SDL_GetWindowFlags(pg_GetDefaultWindow()); + SDL_Window *win = pg_GetDefaultWindow(); + if (!win) { + Py_RETURN_FALSE; + } + SDL_WindowFlags flags = SDL_GetWindowFlags(win); #if SDL_VERSION_ATLEAST(3, 0, 0) return PyBool_FromLong(!(flags & SDL_WINDOW_HIDDEN) && @@ -460,7 +464,12 @@ pg_GetVideoInfo(pg_VideoInfo *info) } else { #if SDL_VERSION_ATLEAST(3, 0, 0) - if ((mode_ptr = SDL_GetCurrentDisplayMode(0))) { + SDL_DisplayID primary_display = SDL_GetPrimaryDisplay(); + if (primary_display == 0) { + PyErr_SetString(pgExc_SDLError, SDL_GetError()); + return (pg_VideoInfo *)NULL; + } + if ((mode_ptr = SDL_GetCurrentDisplayMode(primary_display))) { info->current_w = mode_ptr->w; info->current_h = mode_ptr->h; formatenum = mode_ptr->format; @@ -793,7 +802,7 @@ pg_get_surface(PyObject *self, PyObject *_null) static PyObject * pg_gl_set_attribute(PyObject *self, PyObject *arg) { - int flag, value, result; + int flag, value; VIDEO_INIT_CHECK(); if (!PyArg_ParseTuple(arg, "ii", &flag, &value)) { return NULL; @@ -801,25 +810,35 @@ pg_gl_set_attribute(PyObject *self, PyObject *arg) if (flag == -1) { /*an undefined/unsupported val, ignore*/ Py_RETURN_NONE; } - result = SDL_GL_SetAttribute(flag, value); - if (result == -1) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_GL_SetAttribute(flag, value)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else + if (SDL_GL_SetAttribute(flag, value) == -1) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif Py_RETURN_NONE; } static PyObject * pg_gl_get_attribute(PyObject *self, PyObject *arg) { - int flag, value, result; + int flag, value; VIDEO_INIT_CHECK(); if (!PyArg_ParseTuple(arg, "i", &flag)) { return NULL; } - result = SDL_GL_GetAttribute(flag, &value); - if (result == -1) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_GL_GetAttribute(flag, &value)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else + if (SDL_GL_GetAttribute(flag, &value) == -1) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif return PyLong_FromLong(value); } @@ -1118,12 +1137,12 @@ PG_CreateWindowCompat(const char *title, int x, int y, int w, int h, } #if SDL_VERSION_ATLEAST(3, 0, 0) -/* Returns 0 on success, negative on failure. */ -static int +/* Returns true on success, false on failure. */ +static bool PG_SetWindowFullscreen(SDL_Window *window, bool fullscreen, bool non_desktop_fullscreen) { - int ret = -1; + bool ret = false; SDL_DisplayMode **modes = NULL; SDL_DisplayMode *chosen_mode = NULL; if (!SDL_SetWindowFullscreen(window, fullscreen)) { @@ -1152,11 +1171,24 @@ PG_SetWindowFullscreen(SDL_Window *window, bool fullscreen, } } - ret = 0; + SDL_SyncWindow(window); + ret = true; end: SDL_free(modes); return ret; } +#else +static bool +PG_SetWindowFullscreen(SDL_Window *window, bool fullscreen, + bool non_desktop_fullscreen) +{ + int flags = 0; + if (fullscreen) { + flags = non_desktop_fullscreen ? SDL_WINDOW_FULLSCREEN + : SDL_WINDOW_FULLSCREEN_DESKTOP; + } + return (SDL_SetWindowFullscreen(window, flags) == 0) ? true : false; +} #endif static PyObject * @@ -1235,6 +1267,16 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) } } +#if SDL_VERSION_ATLEAST(3, 0, 0) + /* In SDL2, display == 0 meant primary display, so compat code for it */ + if (display == 0) { + display = SDL_GetPrimaryDisplay(); + if (display == 0) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + } +#endif + if ((vsync == -1) && ((flags & PGS_OPENGL) == 0)) { return RAISE(PyExc_ValueError, "requested adaptive vsync without OpenGL"); @@ -1437,11 +1479,16 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) if (flags & PGS_SCALED && !(flags & PGS_FULLSCREEN)) { SDL_Rect display_bounds; int fractional_scaling = SDL_FALSE; - +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_GetDisplayUsableBounds(display, &display_bounds)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } +#else if (0 != SDL_GetDisplayUsableBounds(display, &display_bounds)) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif if (SDL_GetHintBoolean("SDL_HINT_RENDER_SCALE_QUALITY", SDL_FALSE)) { @@ -1530,9 +1577,9 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) * changes if the window is fullscreen * See https://github.com/pygame/pygame/issues/2711 */ #if SDL_VERSION_ATLEAST(3, 0, 0) - if (0 != PG_SetWindowFullscreen( - win, sdl_flags & SDL_WINDOW_FULLSCREEN, - non_desktop_fullscreen)) { + if (!PG_SetWindowFullscreen(win, + sdl_flags & SDL_WINDOW_FULLSCREEN, + non_desktop_fullscreen)) { return RAISE(pgExc_SDLError, SDL_GetError()); } #else @@ -1592,7 +1639,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) vsync to be always on or always off, or vsync is on by default for the whole desktop because of wayland GL compositing. */ if (vsync == -1) { - if (SDL_GL_SetSwapInterval(-1) != 0) { + if (!PG_GL_SetSwapInterval(-1)) { PyErr_SetString(pgExc_SDLError, "adaptive vsync for OpenGL not " "available"); @@ -1602,7 +1649,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) } } else if (vsync == 1) { - if (SDL_GL_SetSwapInterval(1) != 0) { + if (!PG_GL_SetSwapInterval(1)) { PyErr_SetString(pgExc_SDLError, "regular vsync for OpenGL not " "available"); @@ -1611,7 +1658,7 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) } } else { - SDL_GL_SetSwapInterval(0); + PG_GL_SetSwapInterval(0); } } else { @@ -1849,6 +1896,9 @@ pg_set_mode(PyObject *self, PyObject *arg, PyObject *kwds) } } } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(win); +#endif /*return the window's surface (screen)*/ Py_INCREF(surface); @@ -1947,6 +1997,9 @@ pg_set_window_position(PyObject *self, PyObject *arg) if (win) { /* Will raise errors with SDL 3, deal with it during the porting */ SDL_SetWindowPosition(win, x, y); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(win); +#endif } Py_RETURN_NONE; @@ -1973,7 +2026,16 @@ pg_mode_ok(PyObject *self, PyObject *args, PyObject *kwds) &display_index)) { return NULL; } -#if !SDL_VERSION_ATLEAST(3, 0, 0) + +#if SDL_VERSION_ATLEAST(3, 0, 0) + /* In SDL2, display == 0 meant primary display, so compat code for it */ + if (display_index == 0) { + display_index = SDL_GetPrimaryDisplay(); + if (display_index == 0) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + } +#else /* Display ID is not bounded by number of displays in SDL3 */ if (display_index < 0 || display_index >= SDL_GetNumVideoDisplays()) { return RAISE(PyExc_ValueError, @@ -2000,6 +2062,15 @@ pg_mode_ok(PyObject *self, PyObject *args, PyObject *kwds) } #if SDL_VERSION_ATLEAST(3, 0, 0) + /* Compat with SDL2 behaviour */ + const SDL_DisplayMode *curmode; + if (!(curmode = SDL_GetCurrentDisplayMode(display_index))) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + if (curmode->w == desired.w && curmode->h == desired.h) { + return PyLong_FromLong(SDL_BITSPERPIXEL(curmode->format)); + } + if (!SDL_GetClosestFullscreenDisplayMode(display_index, desired.w, desired.h, desired.refresh_rate, 1, &closest)) { @@ -2039,7 +2110,15 @@ pg_list_modes(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } -#if !SDL_VERSION_ATLEAST(3, 0, 0) +#if SDL_VERSION_ATLEAST(3, 0, 0) + /* In SDL2, display == 0 meant primary display, so compat code for it */ + if (display_index == 0) { + display_index = SDL_GetPrimaryDisplay(); + if (display_index == 0) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + } +#else /* Display ID is not bounded by number of displays in SDL3 */ if (display_index < 0 || display_index >= SDL_GetNumVideoDisplays()) { return RAISE(PyExc_ValueError, @@ -2051,19 +2130,31 @@ pg_list_modes(PyObject *self, PyObject *args, PyObject *kwds) #pragma PG_WARN(Ignoring flags) #if SDL_VERSION_ATLEAST(3, 0, 0) + const SDL_DisplayMode *curmode; + if (!(curmode = SDL_GetCurrentDisplayMode(display_index))) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } if (bpp == 0) { - const SDL_DisplayMode *curmode; - if (!(curmode = SDL_GetCurrentDisplayMode(display_index))) { - return RAISE(pgExc_SDLError, SDL_GetError()); - } bpp = SDL_BITSPERPIXEL(curmode->format); } SDL_DisplayMode **modes = SDL_GetFullscreenDisplayModes(display_index, &nummodes); - if (nummodes < 0) { + if (!modes || nummodes < 0) { return RAISE(pgExc_SDLError, SDL_GetError()); } + + /* SDL3 can return empty list here but SDL2 didn't. In that case, use + * curmode. */ + if (nummodes == 0) { + SDL_free(modes); + modes = SDL_malloc(sizeof(SDL_DisplayMode **)); + if (!modes) { + return PyErr_NoMemory(); + } + modes[0] = (SDL_DisplayMode *)curmode; + nummodes = 1; + } #else if (bpp == 0) { SDL_DisplayMode curmode; @@ -2700,6 +2791,9 @@ pg_iconify(PyObject *self, PyObject *_null) return RAISE(pgExc_SDLError, "No open window"); } SDL_MinimizeWindow(win); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(win); +#endif return PyBool_FromLong(1); } @@ -3035,7 +3129,6 @@ static PyObject * pg_toggle_fullscreen(PyObject *self, PyObject *_null) { SDL_Window *win = pg_GetDefaultWindow(); - int result; SDL_WindowFlags flags; int window_w, window_h, w, h, window_display, x, y; pgSurfaceObject *display_surface; @@ -3164,8 +3257,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) /* TOGGLE FULLSCREEN OFF */ if (state->unscaled_render) { - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 0, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } } @@ -3179,8 +3271,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (scale < 1) { scale = 1; } - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 0, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } SDL_SetWindowSize(win, w * scale, h * scale); @@ -3220,8 +3311,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) /* this is literally the only place where state->toggle_windowed_w * should ever be read. We only use it because with GL, there is no * display surface we can query for dimensions. */ - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 0, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } SDL_GL_MakeCurrent(win, state->gl_context); @@ -3257,8 +3347,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) else if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { #endif - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 0, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3287,15 +3376,11 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (win == NULL) { return RAISE(pgExc_SDLError, SDL_GetError()); } - else { - result = 0; - } display_surface->surf = SDL_GetWindowSurface(win); pg_SetDefaultWindow(win); } else { - result = SDL_SetWindowFullscreen(win, 0); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 0, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3330,24 +3415,12 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) state->fullscreen_backup_y = y; if (state->unscaled_render) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 1, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } } else if (pg_renderer != NULL) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 1, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } if (is_renderer_software && subsystem == SDL_SYSWM_X11) { @@ -3380,13 +3453,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) #endif } else if (state->using_gl) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 1, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } SDL_GL_MakeCurrent(win, state->gl_context); @@ -3411,13 +3478,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } } else if (w == display_mode->w && h == display_mode->h) { -#if SDL_VERSION_ATLEAST(3, 0, 0) - result = PG_SetWindowFullscreen(win, 1, 0); -#else - result = - SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); -#endif - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 1, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3434,8 +3495,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) return PyLong_FromLong(-1); } else { - result = SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN); - if (result != 0) { + if (!PG_SetWindowFullscreen(win, 1, 1)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3447,7 +3507,7 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) if (win == NULL) { return RAISE(pgExc_SDLError, SDL_GetError()); } - if (0 != SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN)) { + if (!PG_SetWindowFullscreen(win, 1, 1)) { return RAISE(pgExc_SDLError, SDL_GetError()); } display_surface->surf = SDL_GetWindowSurface(win); @@ -3461,7 +3521,10 @@ pg_toggle_fullscreen(PyObject *self, PyObject *_null) } } } - return PyLong_FromLong(result != 0); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(win); +#endif + return PyLong_FromLong(1); } /* This API is provisional, and, not finalised, and should not be documented @@ -3539,6 +3602,9 @@ pg_display_resize_event(PyObject *self, PyObject *event) /* do not do anything that would invalidate a display surface! */ return PyLong_FromLong(-1); } +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(win); +#endif Py_RETURN_FALSE; } @@ -3771,7 +3837,11 @@ pg_message_box(PyObject *self, PyObject *arg, PyObject *kwargs) int clicked_button_id; +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_ShowMessageBox(&msgbox_data, &clicked_button_id)) { +#else if (SDL_ShowMessageBox(&msgbox_data, &clicked_button_id)) { +#endif PyErr_SetString(pgExc_SDLError, SDL_GetError()); goto error; } diff --git a/src_c/window.c b/src_c/window.c index 074c514b35..e6dfd0bc1c 100644 --- a/src_c/window.c +++ b/src_c/window.c @@ -301,9 +301,16 @@ _resize_event_watch(void *userdata, SDL_Event *event) static PyObject * window_set_windowed(pgWindowObject *self, PyObject *_null) { +#if SDL_VERSION_ATLEAST(3, 0, 0) + if (!SDL_SetWindowFullscreen(self->_win, 0)) { + return RAISE(pgExc_SDLError, SDL_GetError()); + } + SDL_SyncWindow(self->_win); +#else if (SDL_SetWindowFullscreen(self->_win, 0)) { return RAISE(pgExc_SDLError, SDL_GetError()); } +#endif Py_RETURN_NONE; } @@ -339,6 +346,7 @@ pg_window_set_fullscreen(SDL_Window *window, int desktop) goto end; } + SDL_SyncWindow(window); ret = 1; end: SDL_free(modes); @@ -371,7 +379,7 @@ window_set_fullscreen(pgWindowObject *self, PyObject *args, PyObject *kwargs) static PyObject * window_focus(pgWindowObject *self, PyObject *args, PyObject *kwargs) { - SDL_bool input_only = SDL_FALSE; + int input_only = SDL_FALSE; char *kwids[] = {"input_only", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|p", kwids, &input_only)) { return NULL; @@ -423,6 +431,9 @@ static PyObject * window_restore(pgWindowObject *self, PyObject *_null) { SDL_RestoreWindow(self->_win); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(self->_win); +#endif Py_RETURN_NONE; } @@ -430,6 +441,9 @@ static PyObject * window_maximize(pgWindowObject *self, PyObject *_null) { SDL_MaximizeWindow(self->_win); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(self->_win); +#endif Py_RETURN_NONE; } @@ -437,6 +451,9 @@ static PyObject * window_minimize(pgWindowObject *self, PyObject *_null) { SDL_MinimizeWindow(self->_win); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(self->_win); +#endif Py_RETURN_NONE; } @@ -739,6 +756,9 @@ window_set_size(pgWindowObject *self, PyObject *arg, void *v) } SDL_SetWindowSize(self->_win, w, h); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(self->_win); +#endif if (self->surf) { /* Ensure that the underlying surf is immediately updated, instead of * relying on the event callback */ @@ -791,6 +811,9 @@ window_set_minimum_size(pgWindowObject *self, PyObject *arg, void *v) } SDL_SetWindowMinimumSize(self->_win, w, h); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(self->_win); +#endif return 0; } @@ -831,6 +854,9 @@ window_set_maximum_size(pgWindowObject *self, PyObject *arg, void *v) } SDL_SetWindowMaximumSize(self->_win, w, h); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(self->_win); +#endif return 0; } @@ -862,6 +888,9 @@ window_set_position(pgWindowObject *self, PyObject *arg, void *v) } SDL_SetWindowPosition(self->_win, x, y); +#if SDL_VERSION_ATLEAST(3, 0, 0) + SDL_SyncWindow(self->_win); +#endif return 0; }