Don't send mouse events to hidden scroller children

This commit is contained in:
Nikita Lisitsa 2023-01-05 18:35:39 +03:00
parent 0b358f6877
commit 3f5735e10f
5 changed files with 37 additions and 11 deletions

View file

@ -33,6 +33,8 @@ namespace psemek::ui
virtual async::event_loop * loop() const;
virtual void set_loop(async::event_loop * loop);
virtual geom::box<float, 2> events_bbox() const;
virtual bool on_event(mouse_move const &) { return false; }
virtual bool on_event(mouse_click const &) { return false; }
virtual bool on_event(mouse_wheel const &) { return false; }

View file

@ -24,6 +24,8 @@ namespace psemek::ui
virtual bool horizontal_scroll() const { return horizontal_; }
virtual bool vertical_scroll() const { return vertical_; }
virtual geom::box<float, 2> events_bbox() const override;
virtual bool on_event(mouse_move const & e) override;
virtual bool on_event(mouse_click const & e) override;
virtual bool on_event(mouse_wheel const & e) override;

View file

@ -5,6 +5,7 @@
#include <psemek/gfx/gl.hpp>
#include <psemek/util/recursive.hpp>
#include <psemek/geom/camera.hpp>
#include <psemek/geom/contains.hpp>
namespace psemek::ui
{
@ -73,7 +74,7 @@ namespace psemek::ui
impl(async::event_loop * loop);
template <typename E>
element * event(E const & e);
element * event(E const & e, bool use_event_bbox = false);
element * hinted() const;
@ -87,21 +88,24 @@ namespace psemek::ui
root->set_loop(loop);
root->on_reshape = [this]{
if (mouse)
event(mouse_move{*mouse});
event(mouse_move{*mouse}, true);
};
}
template <typename E>
element * controller::impl::event(E const & e)
element * controller::impl::event(E const & e, bool use_event_bbox)
{
auto visitor = util::recursive([&](auto && self, element * elem) -> element * {
if (elem->hidden()) return nullptr;
auto cs = elem->children();
for (auto it = cs.rbegin(); it != cs.rend(); ++it)
if (*it)
if (auto p = self(*it))
return p;
if (!use_event_bbox || geom::contains(elem->events_bbox(), geom::cast<float>(*mouse)))
{
auto cs = elem->children();
for (auto it = cs.rbegin(); it != cs.rend(); ++it)
if (*it)
if (auto p = self(*it))
return p;
}
if (elem->enabled() && elem->on_event(e)) return elem;
return nullptr;
@ -226,7 +230,7 @@ namespace psemek::ui
bool controller::event(mouse_move const & e)
{
impl().mouse = e.position;
auto result = impl().event(e);
auto result = impl().event(e, true);
if (impl().hinted_element)
{
@ -265,12 +269,12 @@ namespace psemek::ui
bool controller::event(mouse_click const & e)
{
return impl().event(e);
return impl().event(e, static_cast<bool>(impl().mouse));
}
bool controller::event(mouse_wheel const & e)
{
return impl().event(e);
return impl().event(e, static_cast<bool>(impl().mouse));
}
bool controller::event(key_press const & e)

View file

@ -48,6 +48,11 @@ namespace psemek::ui
post_delayed_callbacks();
}
geom::box<float, 2> element::events_bbox() const
{
return geom::box<float, 2>::full();
}
void element::reshape()
{
reshape(shape().bbox());

View file

@ -22,6 +22,19 @@ namespace psemek::ui
return enabled;
}
geom::box<float, 2> scroller::events_bbox() const
{
auto st = merged_own_style();
auto result = shape_.box;
if (horizontal_scroll())
result[1].max -= width() * *st->scale;
if (vertical_scroll())
result[0].max -= width() * *st->scale;
return result;
}
bool scroller::on_event(mouse_move const & e)
{
mouse_ = e.position;