mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-11 21:32:57 +00:00
menu_view: support multiple floats within a frame
This patch refines the hover handling such that a float widget never responds to hovering unless a child is hovered. This way, it becomes possible to stack multiple float widgets within one frame and still reach all child widgets. Issue #3629
This commit is contained in:
parent
49ae4a834f
commit
5aae0f2379
@ -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_ */
|
||||
|
@ -254,6 +254,24 @@ class Menu_view::Widget : List_model<Widget>::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<Widget>::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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user