menu_view: make font-style updates more robust

The font pointers cached in labels can become dangling when the style
database is updated, as happens when changing the font size dynamically.
This patch orderly updates the cached pointers before removing
out-of-date font entries from the style database.

Related to issue #5170
This commit is contained in:
Norman Feske 2024-04-03 22:22:19 +02:00 committed by Christian Helmuth
parent 550dea7279
commit d6cb9cf854
3 changed files with 26 additions and 8 deletions

View File

@ -94,12 +94,12 @@ struct Menu_view::Label_widget : Widget, Cursor::Glyph_position
if (node.has_attribute("text")) { if (node.has_attribute("text")) {
_text = node.attribute_value("text", _text); _text = node.attribute_value("text", _text);
_text = Xml_unquoted(_text); _text = Xml_unquoted(_text);
_min_height = _font->height(); _min_height = _font ? _font->height() : 0;
} }
unsigned const min_ex = node.attribute_value("min_ex", 0U); unsigned const min_ex = node.attribute_value("min_ex", 0U);
if (min_ex) { if (min_ex) {
Glyph_painter::Fixpoint_number min_w_px = _font->string_width("x"); Glyph_painter::Fixpoint_number min_w_px = _font ? _font->string_width("x") : 0;
min_w_px.value *= min_ex; min_w_px.value *= min_ex;
_min_width = min_w_px.decimal(); _min_width = min_w_px.decimal();
} }
@ -154,12 +154,12 @@ struct Menu_view::Label_widget : Widget, Cursor::Glyph_position
*/ */
int xpos_of_glyph(unsigned at) const override int xpos_of_glyph(unsigned at) const override
{ {
return _font->string_width(_text.string(), at).decimal(); return _font ? _font->string_width(_text.string(), at).decimal() : 0;
} }
unsigned _char_index_at_xpos(unsigned xpos) const unsigned _char_index_at_xpos(unsigned xpos) const
{ {
return _font->index_at_xpos(_text.string(), xpos); return _font ? _font->index_at_xpos(_text.string(), xpos) : 0;
} }
Hovered hovered(Point at) const override Hovered hovered(Point at) const override

View File

@ -214,8 +214,6 @@ void Menu_view::Main::_handle_config()
{ {
_config.update(); _config.update();
_styles.flush_outdated_styles();
Xml_node const config = _config.xml(); Xml_node const config = _config.xml();
config.with_optional_sub_node("report", [&] (Xml_node const &report) { config.with_optional_sub_node("report", [&] (Xml_node const &report) {
@ -237,6 +235,20 @@ void Menu_view::Main::_handle_config()
/* update */ /* update */
[&] (Dialog &d, Xml_node const &node) { d.update(node); } [&] (Dialog &d, Xml_node const &node) { d.update(node); }
); );
/* re-assign font pointers in labels (needed due to font style change) */
if (!_styles.up_to_date()) {
_dialogs.for_each([&] (Dialog &dialog) {
dialog._handle_dialog();
/* fast-forward geometry animation on font changes */
while (dialog.animation_in_progress())
dialog.animate();
});
_styles.flush_outdated_styles();
}
trigger_redraw();
} }

View File

@ -65,6 +65,8 @@ class Menu_view::Style_database
Path const path; /* needed for lookup */ Path const path; /* needed for lookup */
Label_style const style; Label_style const style;
bool const out_of_date = false;
static Label_style _init_style(Allocator &alloc, static Label_style _init_style(Allocator &alloc,
Directory const &styles_dir, Directory const &styles_dir,
Path const &path) Path const &path)
@ -96,6 +98,8 @@ class Menu_view::Style_database
Png_image png_image; Png_image png_image;
Texture<Pixel_rgb888> &texture; Texture<Pixel_rgb888> &texture;
bool const out_of_date = false;
void const *_png_data() void const *_png_data()
{ {
void const *result = nullptr; void const *result = nullptr;
@ -183,10 +187,10 @@ class Menu_view::Style_database
T const *_lookup(List<T> &list, char const *path) const T const *_lookup(List<T> &list, char const *path) const
{ {
for (T const *e = list.first(); e; e = e->next()) for (T const *e = list.first(); e; e = e->next())
if (Genode::strcmp(e->path.string(), path) == 0) if ((Genode::strcmp(e->path.string(), path) == 0) && !e->out_of_date)
return e; return e;
return 0; return nullptr;
} }
/* /*
@ -313,6 +317,8 @@ class Menu_view::Style_database
} }
_out_of_date = false; _out_of_date = false;
} }
bool up_to_date() const { return !_out_of_date; }
}; };
#endif /* _STYLE_DATABASE_H_ */ #endif /* _STYLE_DATABASE_H_ */