From 0729823c133e5b1c1c50d05a0923281c3ce0dd41 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 5 Jul 2026 09:47:47 +0200 Subject: [PATCH] fix(image): don't crash at startup when the widget isn't realized yet The HiDPI code path builds a cairo surface from the pixbuf via Gdk::Cairo::create_surface_from_pixbuf(pixbuf, scale, image_.get_window()), which requires a realized Gtk::Image. During startup an image module can run its first update() before the widget is realized, so get_window() returns a null Gdk::Window and that path aborts before anything is logged. The more image modules are configured, the more likely at least one updates before realization, which is why >2 images reliably kills startup. Guard on get_window(): only take the surface path when a window is available, otherwise fall back to image_.set(pixbuf) (the pre-HiDPI behavior). This keeps HiDPI crispness once realized and never crashes at startup. Fixes #5051. --- src/modules/image.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/modules/image.cpp b/src/modules/image.cpp index 7c733880..d762f1eb 100644 --- a/src/modules/image.cpp +++ b/src/modules/image.cpp @@ -265,9 +265,19 @@ void SingleImageStrategy::update() { } if (pixbuf) { - auto surface = Gdk::Cairo::create_surface_from_pixbuf(pixbuf, image_.get_scale_factor(), - image_.get_window()); - image_.set(surface); + // Building a HiDPI-aware cairo surface requires a realized widget: it reads the + // GdkWindow and its scale factor. During startup update() can run before the + // Gtk::Image is realized, in which case get_window() is null; feeding that path a + // null window aborts startup. Fall back to setting the pixbuf directly while the + // widget is unrealized, and use the crisp surface path once a window is available. + auto window = image_.get_window(); + if (window) { + auto surface = + Gdk::Cairo::create_surface_from_pixbuf(pixbuf, image_.get_scale_factor(), window); + image_.set(surface); + } else { + image_.set(pixbuf); + } image_.show(); if (hasTooltip_ && !tooltip_.empty()) {