diff --git a/repos/gems/src/app/menu_view/float_widget.h b/repos/gems/src/app/menu_view/float_widget.h index 78bc79f4b..bb2e4375c 100644 --- a/repos/gems/src/app/menu_view/float_widget.h +++ b/repos/gems/src/app/menu_view/float_widget.h @@ -82,6 +82,32 @@ struct Menu_view::Float_widget : Widget child.size(child.geometry().area()); }); } + + /* + * A float widget cannot be hovered on its own. It only responds to + * hovering if its child is hovered. This way, multiple floats can + * be stacked in one frame without interfering with each other. + */ + + Hovered hovered(Point at) const override + { + Hovered const result = Widget::hovered(at); + + /* respond positively whenever one of our children is hovered */ + if (result.unique_id != _unique_id) + return result; + + return { .unique_id = { }, .detail = { } }; + } + + void gen_hover_model(Xml_generator &xml, Point at) const override + { + /* omit ourself from hover model unless one of our children is hovered */ + if (!_inner_geometry().contains(at)) + return; + + Widget::gen_hover_model(xml, at); + } }; #endif /* _FLOAT_WIDGET_H_ */ diff --git a/repos/gems/src/app/menu_view/widget.h b/repos/gems/src/app/menu_view/widget.h index 8feb463cc..fe928b3b5 100644 --- a/repos/gems/src/app/menu_view/widget.h +++ b/repos/gems/src/app/menu_view/widget.h @@ -254,6 +254,24 @@ class Menu_view::Widget : List_model::Element _geometry = Rect(position, _geometry.area()); } + static Point _at_child(Point at, Widget const &w) + { + return at - w.geometry().p1(); + } + + static bool _child_hovered(Point at, Widget const &w) + { + return w.hovered(_at_child(at, w)).unique_id.valid(); + } + + bool _any_child_hovered(Point at) const + { + bool result = false; + _children.for_each([&] (Widget const &w) { + result = result | _child_hovered(at, w); }); + return result; + } + /** * Return unique ID of inner-most hovered widget * @@ -265,33 +283,37 @@ class Menu_view::Widget : List_model::Element return { }; Hovered result { .unique_id = _unique_id, .detail = { } }; + + if (!_any_child_hovered(at)) + return result; + _children.for_each([&] (Widget const &w) { - Hovered const hovered = w.hovered(at - w.geometry().p1()); + Hovered const hovered = w.hovered(_at_child(at, w)); if (hovered.unique_id.valid()) - result = hovered; - }); + result = hovered; }); return result; } + virtual void gen_hover_model(Xml_generator &xml, Point at) const + { + if (!_inner_geometry().contains(at)) + return; + + xml.node(_type_name.string(), [&]() { + + _gen_common_hover_attr(xml); + + _children.for_each([&] (Widget const &w) { + if (_child_hovered(at, w)) + w.gen_hover_model(xml, _at_child(at, w)); }); + }); + } + void print(Output &out) const { Genode::print(out, _name); } - - virtual void gen_hover_model(Xml_generator &xml, Point at) const - { - if (_inner_geometry().contains(at)) { - - xml.node(_type_name.string(), [&]() { - - _gen_common_hover_attr(xml); - - _children.for_each([&] (Widget const &w) { - w.gen_hover_model(xml, at - w.geometry().p1()); }); - }); - } - } }; #endif /* _WIDGET_H_ */