From 3f5735e10f00faf675984a65419b0b9f5725a6c6 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 5 Jan 2023 18:35:39 +0300 Subject: [PATCH] Don't send mouse events to hidden scroller children --- libs/ui/include/psemek/ui/element.hpp | 2 ++ libs/ui/include/psemek/ui/scroller.hpp | 2 ++ libs/ui/source/controller.cpp | 26 +++++++++++++++----------- libs/ui/source/element.cpp | 5 +++++ libs/ui/source/scroller.cpp | 13 +++++++++++++ 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/libs/ui/include/psemek/ui/element.hpp b/libs/ui/include/psemek/ui/element.hpp index 5d968ce4..7faafb96 100644 --- a/libs/ui/include/psemek/ui/element.hpp +++ b/libs/ui/include/psemek/ui/element.hpp @@ -33,6 +33,8 @@ namespace psemek::ui virtual async::event_loop * loop() const; virtual void set_loop(async::event_loop * loop); + virtual geom::box 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; } diff --git a/libs/ui/include/psemek/ui/scroller.hpp b/libs/ui/include/psemek/ui/scroller.hpp index ea820e31..6e5c5237 100644 --- a/libs/ui/include/psemek/ui/scroller.hpp +++ b/libs/ui/include/psemek/ui/scroller.hpp @@ -24,6 +24,8 @@ namespace psemek::ui virtual bool horizontal_scroll() const { return horizontal_; } virtual bool vertical_scroll() const { return vertical_; } + virtual geom::box 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; diff --git a/libs/ui/source/controller.cpp b/libs/ui/source/controller.cpp index b235c331..a72f2edd 100644 --- a/libs/ui/source/controller.cpp +++ b/libs/ui/source/controller.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace psemek::ui { @@ -73,7 +74,7 @@ namespace psemek::ui impl(async::event_loop * loop); template - 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 - 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(*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(impl().mouse)); } bool controller::event(mouse_wheel const & e) { - return impl().event(e); + return impl().event(e, static_cast(impl().mouse)); } bool controller::event(key_press const & e) diff --git a/libs/ui/source/element.cpp b/libs/ui/source/element.cpp index f53ef0f8..d6c65b81 100644 --- a/libs/ui/source/element.cpp +++ b/libs/ui/source/element.cpp @@ -48,6 +48,11 @@ namespace psemek::ui post_delayed_callbacks(); } + geom::box element::events_bbox() const + { + return geom::box::full(); + } + void element::reshape() { reshape(shape().bbox()); diff --git a/libs/ui/source/scroller.cpp b/libs/ui/source/scroller.cpp index b94ceb87..7b90a346 100644 --- a/libs/ui/source/scroller.cpp +++ b/libs/ui/source/scroller.cpp @@ -22,6 +22,19 @@ namespace psemek::ui return enabled; } + geom::box 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;