diff --git a/adapters/glfw/glfw_host.cpp b/adapters/glfw/glfw_host.cpp index aed7157..540b129 100644 --- a/adapters/glfw/glfw_host.cpp +++ b/adapters/glfw/glfw_host.cpp @@ -103,6 +103,12 @@ void Host::close() noexcept { glfwMakeContextCurrent(nullptr); glfwTerminate(); 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) { @@ -172,7 +178,17 @@ bool Host::run(const RunConfig& cfg, const FrameFn& frame, Status* st) { if (fb_width_ == 0 || fb_height_ == 0) { // 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); continue; } @@ -224,8 +240,13 @@ void Host::refresh_sizes() noexcept { glfwGetWindowContentScale(window_, &sx, &sy); content_scale_x_ = sx; content_scale_y_ = sy; - if (fw > 0) fb_width_ = static_cast(fw); - if (fh > 0) fb_height_ = static_cast(fh); + // Assigned unconditionally, zero included: an iconified window really does + // 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(fw) : 0u; + fb_height_ = fh > 0 ? static_cast(fh) : 0u; if (ww > 0 && fw > 0) fb_scale_x_ = static_cast(fw) / static_cast(ww); if (wh > 0 && fh > 0) fb_scale_y_ = static_cast(fh) / static_cast(wh); }