Quick answer: Pygame VIDEORESIZE event arriving with the old size? Use event.size or event.w/event.h, not pygame.display.get_surface() — the surface isn’t updated until you call set_mode.
On resize, the game uses display.get_surface().get_size() and gets the pre-resize values, leading to layout glitches.
Event Carries New Size
if event.type == pygame.VIDEORESIZE:
screen = pygame.display.set_mode(event.size, pygame.RESIZABLE)
layout(event.size)The event’s size tuple is the target size. Use it to re-create the display surface, then re-layout.
Coalesce Drag Events
Resize fires every drag pixel. Coalesce by storing the latest size and only resizing the display once per frame — resize is expensive.
VIDEOEXPOSE vs VIDEORESIZE
VIDEOEXPOSE fires when the OS redraws over your window (e.g. after another window moves). Trigger a full repaint, but don’t resize.
Verifying
Dragging the window edge resizes cleanly. Layout adapts to the new size without holding old dimensions.
“Resize event carries the new size. Use it, don’t query the old surface.”
On Linux/X11, VIDEORESIZE during fast drags can flood — debouncing to 30Hz inside the resize handler keeps it cheap.