diff --git a/src/gui/core/event/dispatcher.cpp b/src/gui/core/event/dispatcher.cpp index 43c1d2c59da3..be6fbadb153c 100644 --- a/src/gui/core/event/dispatcher.cpp +++ b/src/gui/core/event/dispatcher.cpp @@ -57,50 +57,12 @@ void dispatcher::connect() bool dispatcher::has_event(const ui_event event, const event_queue_type event_type) { #if 0 - // Debug code to test whether the event is in the right queue. - std::cerr << "Event '" << event - << "' event " - << find(event, dispatcher_implementation - ::has_handler(event_type, *this)) - << " mouse " - << find(event, dispatcher_implementation - ::has_handler(event_type, *this)) - << " keyboard " - << find(event, dispatcher_implementation - ::has_handler(event_type, *this)) - << " touch_motion " - << find(event, dispatcher_implementation - ::has_handler(event_type, *this)) - << " touch_gesture " - << find(event, dispatcher_implementation - ::has_handler(event_type, *this)) - << " notification " - << find(event, dispatcher_implementation - ::has_handler(event_type, *this)) - << " message " - << find(event, dispatcher_implementation - ::has_handler(event_type, *this)) - << ".\n"; + const bool res = dispatcher_implementation::has_handler(*this, event_type, event); + std::cerr << "Event '" << event << " '" << (res ? "found" : "not found") << "in queue\n"; + return res; +#else + return dispatcher_implementation::has_handler(*this, event_type, event); #endif - - return find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)) - || find( - event, dispatcher_implementation::has_handler(event_type, *this)); } bool dispatcher::fire(const ui_event event, widget& target) @@ -154,7 +116,7 @@ bool dispatcher::fire(const ui_event event, widget& target, const point& center, bool dispatcher::fire(const ui_event event, widget& target, const SDL_Event& sdlevent) { - assert(is_raw_event(event)); + assert(is_raw_event_event(event)); return fire_event(event, this, &target, sdlevent); } diff --git a/src/gui/core/event/dispatcher.hpp b/src/gui/core/event/dispatcher.hpp index 749af5fa3761..4bef49c79370 100644 --- a/src/gui/core/event/dispatcher.hpp +++ b/src/gui/core/event/dispatcher.hpp @@ -157,7 +157,7 @@ constexpr bool is_message_event(const ui_event event) * * This version is for callbacks of raw events. */ -constexpr bool is_raw_event(const ui_event event) +constexpr bool is_raw_event_event(const ui_event event) { return event == SDL_RAW_EVENT; } @@ -755,7 +755,7 @@ class dispatcher * @param position The position to place the callback. */ template - std::enable_if_t + std::enable_if_t connect_signal(const signal_raw_event_function& signal, const queue_position position = back_child) { signal_raw_event_queue_.connect_signal(E, position, signal); @@ -772,7 +772,7 @@ class dispatcher * was added in front or back.) */ template - std::enable_if_t + std::enable_if_t disconnect_signal(const signal_raw_event_function& signal, const queue_position position = back_child) { signal_raw_event_queue_.disconnect_signal(E, position, signal); @@ -877,6 +877,32 @@ class dispatcher std::list pre_child; std::list child; std::list post_child; + + /** + * Checks whether the queue of a given type is empty. + * + * @param queue_type The queue to check. This may be one or more types + * OR'd together (event_queue_type is bit-unique). + * + * @returns True if ALL the matching queues are empty, or false + * if any of the matching queues is NOT empty. + */ + bool empty(const dispatcher::event_queue_type queue_type) const + { + if((queue_type & dispatcher::pre) && !pre_child.empty()) { + return false; + } + + if((queue_type & dispatcher::child) && !child.empty()) { + return false; + } + + if((queue_type & dispatcher::post) && !post_child.empty()) { + return false; + } + + return true; + } }; /** Helper struct to generate the various event queues. */ diff --git a/src/gui/core/event/dispatcher_private.hpp b/src/gui/core/event/dispatcher_private.hpp index 34ae846809e1..cd181271724b 100644 --- a/src/gui/core/event/dispatcher_private.hpp +++ b/src/gui/core/event/dispatcher_private.hpp @@ -20,7 +20,6 @@ #include -#include #include namespace gui2 @@ -65,27 +64,6 @@ struct dispatcher_implementation { \ return dispatcher.QUEUE.queue[event]; \ } \ - \ - /** \ - * Returns the signal structure for a key in SET. \ - * \ - * There are several functions that only overload the return value, in \ - * order to do so they use SFINAE. \ - * \ - * @tparam K A key in set_event. \ - * @param dispatcher The dispatcher whose signal queue is used. \ - * @param event The event to get the signal for. \ - * \ - * @returns The signal of the type \ - * dispatcher::signal_type \ - */ \ - template \ - static std::enable_if_t::value, dispatcher::signal_type>& \ - event_signal(dispatcher& dispatcher, const ui_event event) \ - { \ - return dispatcher.QUEUE.queue[event]; \ - } - IMPLEMENT_EVENT_SIGNAL(set_event, signal_function, signal_queue_) @@ -115,137 +93,45 @@ struct dispatcher_implementation #undef IMPLEMENT_EVENT_SIGNAL_WRAPPER #undef IMPLEMENT_EVENT_SIGNAL +#define IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(TYPE) \ + else if(is_##TYPE##_event(event)) { \ + return queue_check(dispatcher.signal_##TYPE##_queue_); \ + } + /** - * A helper class to find out whether dispatcher has an handler for a - * certain event. + * A helper to test whether dispatcher has an handler for a certain event. + * + * @param dispatcher The dispatcher whose signal queue is used. + * @param queue_type The type of event to look for. + * @param event The event to get the signal for. + * + * @returns Whether or not the handler is found. */ - class has_handler + static bool has_handler(dispatcher& dispatcher, const dispatcher::event_queue_type queue_type, ui_event event) { - public: - /** - * Constructor. - * - * @param event_type The type of event to look for. - * @param dispatcher The dispatcher whose signal queue is used. - */ - has_handler(const dispatcher::event_queue_type event_type, dispatcher& dispatcher) - : event_type_(event_type), dispatcher_(dispatcher) - { - } - - /** - * Tests whether a handler for an event is available. - * - * It tests for both the event and the event_type send in the - * constructor. - * - * @tparam T A key from an event set used to instantiate - * the proper @p event_signal function. - * @param event The event to get the signal for. - * - * @returns Whether or not the handler is found. - */ - // not called operator() to work around a problem in MSVC - // (known to affect all versions up to 2015) - template - bool oper(ui_event event) - { - if((event_type_ & dispatcher::pre) - && !event_signal(dispatcher_, event).pre_child.empty()) { - return true; - } + const auto queue_check = [&](auto& queue_set) { + return !queue_set.queue[event].empty(queue_type); + }; - if((event_type_ & dispatcher::child) - && !event_signal(dispatcher_, event).child.empty()) { - return true; - } - - if((event_type_ & dispatcher::post) - && !event_signal(dispatcher_, event).post_child.empty()) { - return true; - } - - return false; + if(is_general_event(event)) { + return queue_check(dispatcher.signal_queue_); } - private: - dispatcher::event_queue_type event_type_; - dispatcher& dispatcher_; - }; -}; + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(mouse) + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(keyboard) + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(touch_motion) + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(touch_gesture) + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(notification) + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(message) + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(raw_event) + IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK(text_input) -/** Contains the implementation details of the find function. */ -namespace implementation -{ - -/** Specialized class when itor == end */ -template -struct find -{ - template - static bool execute(itor*, end*, E, F) - { return false; } -}; -/** Specialized class when itor != end */ -template<> -struct find -{ - template - static bool execute(itor*, end*, E event, F functor) - { - typedef typename boost::mpl::deref::type item; - typedef typename boost::mpl::apply1, item>::type arg; - - boost::value_initialized x; - - if(boost::get(x) == event) { - return functor.template oper(event); - } else { - typedef typename boost::mpl::next::type itor_t; - return find::value>::execute( - static_cast(nullptr), - static_cast(nullptr), - event, - functor); - } - } +#undef IMPLEMENT_RUNTIME_EVENT_SIGNAL_CHECK }; -} // namespace implementation - -/** - * Tests whether an event handler is available. - * - * The code is based on boost::mpl_for_each, which doesn't allow to call a - * template function with the dereferred iterator as template parameter. - * - * The function first tries to match whether the value in the sequence matches - * event, once that matched it will execute the functor with the key found as - * template parameter and the event as parameter. - * - * @tparam sequence The sequence to test upon. - * @tparam E The value type of the item in the sequence - * @tparam F Type of the functor. - * - * @param event The event to look for. - * @param functor The predicate which should is executed if the - * event is matched. - * - * @returns Whether or not the function found a result. - */ -template -inline bool find(E event, F functor) -{ - typedef typename boost::mpl::begin::type begin; - typedef typename boost::mpl::end::type end; - - return implementation::find::value>::execute( - static_cast(nullptr), static_cast(nullptr), event, functor); -} - namespace implementation { diff --git a/src/gui/core/event/handler.hpp b/src/gui/core/event/handler.hpp index a9bc8ec4210b..45b538da25a2 100644 --- a/src/gui/core/event/handler.hpp +++ b/src/gui/core/event/handler.hpp @@ -14,14 +14,6 @@ #pragma once -#ifdef BOOST_MPL_LIMIT_SET_SIZE -#undef BOOST_MPL_LIMIT_SET_SIZE -#endif -#define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS -#define BOOST_MPL_LIMIT_SET_SIZE 30 - -#include - #include #include @@ -121,127 +113,6 @@ enum ui_event { SDL_RAW_EVENT /**< Raw SDL event. */ }; -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This helper is needed as a user can't supply the wrong kind of callback - * functions to dispatcher::connect_signal. If a wrong callback would be send - * it will never get called. - * - * This version is for callbacks without extra parameters. - * NOTE some mouse functions like MOUSE_ENTER don't send the mouse coordinates - * to the callback function so they are also in this category. - */ -typedef boost::mpl::set, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_> -set_event; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks with a coordinate as extra parameter. - */ -typedef boost::mpl::set, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_> set_event_mouse; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks with the keyboard values (these haven't been - * determined yet). - */ -typedef boost::mpl::set> set_event_keyboard; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks of touch motion events. - */ -typedef boost::mpl::set> -set_event_touch_motion; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks of touch gestures events. - */ -typedef boost::mpl::set> -set_event_touch_gesture; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks with a sender aka notification messages. Like - *the - * ones in set_event it has no extra parameters, but this version is only - * send to the target and not using the pre and post queue. - */ -typedef boost::mpl::set, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_, - boost::mpl::int_> -set_event_notification; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks with a sender aka notification messages. - * Unlike the notifications this message is send through the chain. The event - * is send from a widget all the way up to the window, who always is the - * receiver of the message (unless somebody grabbed it before). - */ -typedef boost::mpl::set, - boost::mpl::int_, - boost::mpl::int_> -set_event_message; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks of raw events. - */ -typedef boost::mpl::set> set_event_raw_event; - -/** - * Helper for catching use error of dispatcher::connect_signal. - * - * This version is for callbacks of text input events. - */ -typedef boost::mpl::set, - boost::mpl::int_> -set_event_text_input; - /** * Connects a dispatcher to the event handler. *