fix(glfw): report a zero framebuffer size so the no-drawable guard is reachable

This commit is contained in:
Martino Ferrari committed 2026-09-28 00:07:51 +02:00
1 parent 0ac5d47fa6
commit c8a97e4a1b
1 file changed
+24 -3
+24 -3
View File
@@ -103,6 +103,12 @@ void Host::close() noexcept {
glfwMakeContextCurrent(nullptr); glfwMakeContextCurrent(nullptr);
glfwTerminate(); glfwTerminate();
have_pointer_ = false; have_pointer_ = false;
// A closed host reports no size: a second run() must not see the previous
// window's framebuffer size before its first refresh_sizes().
fb_width_ = 0;
fb_height_ = 0;
fb_scale_x_ = 1.0f;
fb_scale_y_ = 1.0f;
} }
bool Host::run(const RunConfig& cfg, const FrameFn& frame, Status* st) { bool Host::run(const RunConfig& cfg, const FrameFn& frame, Status* st) {
@@ -172,7 +178,17 @@ bool Host::run(const RunConfig& cfg, const FrameFn& frame, Status* st) {
if (fb_width_ == 0 || fb_height_ == 0) { if (fb_width_ == 0 || fb_height_ == 0) {
// Minimised, or a size the compositor reports as zero: nothing to draw // Minimised, or a size the compositor reports as zero: nothing to draw
// into. Idle briefly rather than spin, so an exit deadline still lands. // into, and nothing to hand `begin_frame` -- a stale larger size would be
// a lie about the framebuffer. Idle on events rather than spin, and still
// honour the exit deadline here: a bounded run that never gets a drawable
// must end, not idle past the deadline it was given. There is no frame to
// dump in this state, so the screenshot is skipped.
if (exit_after_s > 0.0 && glfwGetTime() - start >= exit_after_s) {
std::fprintf(stderr,
"[glfw] exit deadline reached with no drawable (framebuffer 0x0);"
" nothing to dump\n");
break;
}
glfwWaitEventsTimeout(0.05); glfwWaitEventsTimeout(0.05);
continue; continue;
} }
@@ -224,8 +240,13 @@ void Host::refresh_sizes() noexcept {
glfwGetWindowContentScale(window_, &sx, &sy); glfwGetWindowContentScale(window_, &sx, &sy);
content_scale_x_ = sx; content_scale_x_ = sx;
content_scale_y_ = sy; content_scale_y_ = sy;
if (fw > 0) fb_width_ = static_cast<u32>(fw); // Assigned unconditionally, zero included: an iconified window really does
if (fh > 0) fb_height_ = static_cast<u32>(fh); // report a 0x0 framebuffer (Windows, and several Linux window managers), and
// the loop's no-drawable guard reads exactly this. Only ever writing a
// positive size would leave the guard unreachable and keep handing
// `begin_frame` a stale size for a framebuffer that is no longer that big.
fb_width_ = fw > 0 ? static_cast<u32>(fw) : 0u;
fb_height_ = fh > 0 ? static_cast<u32>(fh) : 0u;
if (ww > 0 && fw > 0) fb_scale_x_ = static_cast<f32>(fw) / static_cast<f32>(ww); if (ww > 0 && fw > 0) fb_scale_x_ = static_cast<f32>(fw) / static_cast<f32>(ww);
if (wh > 0 && fh > 0) fb_scale_y_ = static_cast<f32>(fh) / static_cast<f32>(wh); if (wh > 0 && fh > 0) fb_scale_y_ = static_cast<f32>(fh) / static_cast<f32>(wh);
} }