diff --git a/src/gui/core/event/dispatcher.cpp b/src/gui/core/event/dispatcher.cpp index 6335256213ceb..8dde246214bf6 100644 --- a/src/gui/core/event/dispatcher.cpp +++ b/src/gui/core/event/dispatcher.cpp @@ -96,7 +96,10 @@ bool dispatcher::has_event(const ui_event event, const event_queue_type event_ty *this)) || find(event, dispatcher_implementation::has_handler( - event_type, *this)); + event_type, *this)) + || find(event, + dispatcher_implementation::has_handler( + event_type, *this)); } /** @@ -250,6 +253,39 @@ bool dispatcher::fire(const ui_event event, trigger_keyboard(key, modifier, unicode)); } +/** Helper struct to wrap the functor call. */ +class trigger_raw_event +{ +public: + trigger_raw_event(const SDL_Event& sdlevent) : sdl_event_(sdlevent) + { + } + + void operator()(signal_raw_event_function functor, + dispatcher& dispatcher, + const ui_event event, + bool& handled, + bool& halt) + { + functor(dispatcher, event, handled, halt, sdl_event_); + } + +private: + const SDL_Event& sdl_event_; +}; + +bool dispatcher::fire(const ui_event event, + widget& target, + const SDL_Event& sdlevent) +{ + assert(find(event, event_in_set())); + return fire_event( + event, + dynamic_cast(this), + &target, + trigger_raw_event(sdlevent)); +} + /** Helper struct to wrap the functor call. */ class trigger_touch { diff --git a/src/gui/core/event/dispatcher.hpp b/src/gui/core/event/dispatcher.hpp index 6ce0b330da153..61963f7c8fcb2 100644 --- a/src/gui/core/event/dispatcher.hpp +++ b/src/gui/core/event/dispatcher.hpp @@ -49,9 +49,9 @@ struct message; * * This function is used for the callbacks in set_event. */ -typedef std::function -signal_function; +typedef std::function signal_function; /** * Callback function signature. @@ -75,8 +75,7 @@ typedef std::function -signal_keyboard_function; + const utf8::string& unicode)> signal_keyboard_function; /** * Callback function signature. @@ -88,8 +87,7 @@ typedef std::function -signal_touch_function; + const point& distance)> signal_touch_function; /** * Callback function signature. @@ -115,6 +113,17 @@ typedef std::function signal_message_function; + /** + * Callback function signature. + * + * This function is used for the callbacks in set_event_message. + */ +typedef std::function signal_raw_event_function; + /** Hotkey function handler signature. */ typedef std::function thotkey_function; @@ -185,7 +194,9 @@ class dispatcher * @param target The widget that should receive the event. * @param coordinate The mouse position for the event. */ - bool fire(const ui_event event, widget& target, const point& coordinate); + bool fire(const ui_event event, + widget& target, + const point& coordinate); /** * Fires an event which takes keyboard parameters. @@ -223,7 +234,9 @@ class dispatcher * @param event The event to fire. * @param target The widget that should receive the event. */ - bool fire(const ui_event event, widget& target, void*); + bool fire(const ui_event event, + widget& target, + void*); /** * Fires an event which takes message parameters. @@ -236,7 +249,21 @@ class dispatcher * (or another widget in the chain) to handle * the message. */ - bool fire(const ui_event event, widget& target, message& msg); + bool fire(const ui_event event, + widget& target, + message& msg); + + /** + * Fires an event that's a raw SDL event + * @param event The event to fire. + * @param target The widget that should receive the event. + * Normally this is the window holding the + * widget. + * @param sdlevent The raw SDL event + */ + bool fire(const ui_event event, + widget& target, + const SDL_Event& sdlevent); /** * The position where to add a new callback in the signal handler. @@ -507,6 +534,39 @@ class dispatcher signal_message_queue_.disconnect_signal(E, position, signal); } + /** + * Connect a signal for callback in set_raw_event. + * + * @tparam E The event the callback needs to react to. + * @param signal The callback function. + * @param position The position to place the callback. + */ + template + typename std::enable_if::value>::type + connect_signal(const signal_raw_event_function& signal, + const queue_position position = back_child) + { + signal_raw_event_queue_.connect_signal(E, position, signal); + } + + /** + * Disconnect a signal for callback in set_raw_event. + * + * @tparam E The event the callback was used for. + * @param signal The callback function. + * @param position The place where the function was added. + * Needed remove the event from the right + * place. (The function doesn't care whether + * was added in front or back.) + */ + template + typename std::enable_if::value>::type + disconnect_signal(const signal_raw_event_function& signal, + const queue_position position = back_child) + { + signal_raw_event_queue_.disconnect_signal(E, position, signal); + } + /** * The behavior of the mouse events. * @@ -733,6 +793,9 @@ class dispatcher /** Signal queue for callbacks in set_event_message. */ signal_queue signal_message_queue_; + /** Signal queue for callbacks in set_raw_event. */ + signal_queue signal_raw_event_queue_; + /** Are we connected to the event handler. */ bool connected_; diff --git a/src/gui/core/event/dispatcher_private.hpp b/src/gui/core/event/dispatcher_private.hpp index 94683decb3c5b..6563cfb8efb89 100644 --- a/src/gui/core/event/dispatcher_private.hpp +++ b/src/gui/core/event/dispatcher_private.hpp @@ -110,6 +110,7 @@ struct dispatcher_implementation IMPLEMENT_EVENT_SIGNAL_WRAPPER(touch) IMPLEMENT_EVENT_SIGNAL_WRAPPER(notification) IMPLEMENT_EVENT_SIGNAL_WRAPPER(message) + IMPLEMENT_EVENT_SIGNAL_WRAPPER(raw_event) #undef IMPLEMENT_EVENT_SIGNAL_WRAPPER #undef IMPLEMENT_EVENT_SIGNAL diff --git a/src/gui/core/event/handler.cpp b/src/gui/core/event/handler.cpp index 31bd56bf8ffe1..35c538977c71c 100644 --- a/src/gui/core/event/handler.cpp +++ b/src/gui/core/event/handler.cpp @@ -164,6 +164,9 @@ class sdl_event_handler : public events::sdl_handler /***** Handlers *****/ + /** Fires a raw SDL event. */ + void raw_event(const SDL_Event &event); + /** Fires a draw event. */ using events::sdl_handler::draw; void draw(const bool force); @@ -445,6 +448,8 @@ void sdl_event_handler::handle_event(const SDL_Event& event) #endif break; } + + raw_event(event); } void sdl_event_handler::handle_window_event(const SDL_Event& event) @@ -559,6 +564,15 @@ void sdl_event_handler::video_resize(const point& new_size) } } +void sdl_event_handler::raw_event(const SDL_Event& event) { + DBG_GUI_E << "Firing raw event\n"; + + for(auto dispatcher : dispatchers_) + { + dispatcher->fire(SDL_RAW_EVENT, dynamic_cast(*dispatcher), event); + } +} + void sdl_event_handler::mouse(const ui_event event, const point& position) { DBG_GUI_E << "Firing: " << event << ".\n"; @@ -961,6 +975,9 @@ std::ostream& operator<<(std::ostream& stream, const ui_event event) case SDL_TOUCH_DOWN: stream << "SDL touch down"; break; + case SDL_RAW_EVENT: + stream << "SDL raw event"; + break; } return stream; diff --git a/src/gui/core/event/handler.hpp b/src/gui/core/event/handler.hpp index ee57d762eddaf..8dc8dffc89f5c 100644 --- a/src/gui/core/event/handler.hpp +++ b/src/gui/core/event/handler.hpp @@ -113,7 +113,9 @@ enum ui_event { SDL_TOUCH_MOTION, SDL_TOUCH_UP, - SDL_TOUCH_DOWN + SDL_TOUCH_DOWN, + + SDL_RAW_EVENT /**< Raw SDL event. */ }; /** @@ -213,6 +215,13 @@ typedef boost::mpl::set, 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; + /** * Connects a dispatcher to the event handler. * diff --git a/src/gui/dialogs/hotkey_bind.cpp b/src/gui/dialogs/hotkey_bind.cpp index 2006ca7e6f001..74156a32a005f 100644 --- a/src/gui/dialogs/hotkey_bind.cpp +++ b/src/gui/dialogs/hotkey_bind.cpp @@ -36,37 +36,20 @@ hotkey_bind::hotkey_bind(const std::string& hotkey_id) void hotkey_bind::pre_show(window& window) { - connect_signal_pre_key_press(window, std::bind(&hotkey_bind::key_press_callback, this, std::ref(window), _5)); + window.connect_signal( + std::bind(&hotkey_bind::sdl_event_callback, this, std::ref(window), _5), + event::dispatcher::front_child); - window.connect_signal( - std::bind(&hotkey_bind::mouse_button_callback, this, std::ref(window), SDL_BUTTON_LEFT), event::dispatcher::front_child); - window.connect_signal( - std::bind(&hotkey_bind::mouse_button_callback, this, std::ref(window), SDL_BUTTON_MIDDLE), event::dispatcher::front_child); - window.connect_signal( - std::bind(&hotkey_bind::mouse_button_callback, this, std::ref(window), SDL_BUTTON_RIGHT), event::dispatcher::front_child); } -void hotkey_bind::key_press_callback(window& window, const SDL_Keycode key) +void hotkey_bind::sdl_event_callback(window& win, const SDL_Event &event) { - /* HACK: SDL_KEYDOWN and SDL_TEXTINPUT events forward to the same GUI2 event (SDL_KEY_DOWN), meaning - * this even gets fired twice, causing problems since 'key' will be 0 in the latter case. SDLK_UNKNOWN - * is the key value used by SDL_TEXTINPUT handling, so exit here if that's detected. - */ - if(key == SDLK_UNKNOWN) { - return; + if (hotkey::is_hotkeyable_event(event)) { + new_binding_ = hotkey::create_hotkey(hotkey_id_, event); + win.set_retval(window::OK); } - - new_binding_ = hotkey::create_hotkey(hotkey_id_, SDL_GetScancodeFromKey(key)); - - window.set_retval(window::OK); } -void hotkey_bind::mouse_button_callback(window& window, Uint8 button) -{ - new_binding_ = hotkey::create_hotkey(hotkey_id_, button); - - window.set_retval(window::OK); -} } // namespace dialogs } // namespace gui2 diff --git a/src/gui/dialogs/hotkey_bind.hpp b/src/gui/dialogs/hotkey_bind.hpp index 12a3bb05de9b5..c555cef314cdd 100644 --- a/src/gui/dialogs/hotkey_bind.hpp +++ b/src/gui/dialogs/hotkey_bind.hpp @@ -41,9 +41,7 @@ class hotkey_bind : public modal_dialog hotkey::hotkey_ptr new_binding_; - void key_press_callback(window& window, const SDL_Keycode key); - - void mouse_button_callback(window& window, Uint8 button); + void sdl_event_callback(window& win, const SDL_Event &event); /** Inherited from modal_dialog, implemented by REGISTER_DIALOG. */ virtual const std::string& window_id() const override; diff --git a/src/hotkey/hotkey_item.cpp b/src/hotkey/hotkey_item.cpp index d5cb484ecbe49..2bffc9a9c6a91 100644 --- a/src/hotkey/hotkey_item.cpp +++ b/src/hotkey/hotkey_item.cpp @@ -143,7 +143,7 @@ void hotkey_base::save(config& item) const save_helper(item); } -hotkey_ptr create_hotkey(const std::string &id, SDL_Event &event) +hotkey_ptr create_hotkey(const std::string &id, const SDL_Event &event) { hotkey_ptr base = hotkey_ptr(new hotkey_void); unsigned mods = sdl_get_mods(); @@ -450,7 +450,7 @@ void save_hotkeys(config& cfg) } } -std::string get_names(std::string id) +std::string get_names(const std::string& id) { // Names are used in places like the hot-key preferences menu std::vector names; diff --git a/src/hotkey/hotkey_item.hpp b/src/hotkey/hotkey_item.hpp index 47ae38e536575..a2114f34497c5 100644 --- a/src/hotkey/hotkey_item.hpp +++ b/src/hotkey/hotkey_item.hpp @@ -379,11 +379,12 @@ void add_hotkey(const hotkey_ptr item); */ void del_hotkey(const hotkey_ptr item); -/** Create a new hotkey item bound to a keyboard key. */ -hotkey_ptr create_hotkey(const std::string& id, SDL_Scancode new_val); - -/** Create a new hotkey item bound to a mouse button. */ -hotkey_ptr create_hotkey(const std::string& id, Uint8 new_val); +/** + * Create a new hotkey item for a command from an SDL_Event. + * @param id The command to bind to. + * @param event The SDL_Event to base the creation on. + */ +hotkey_ptr create_hotkey(const std::string &id, const SDL_Event &event); /** * Iterate through the list of hotkeys and return a hotkey that matches @@ -437,8 +438,6 @@ std::string get_names(const std::string& id); */ void save_hotkeys(config& cfg); -hotkey_ptr show_binding_dialog(CVideo& video, const std::string& id); - bool is_hotkeyable_event(const SDL_Event &event); }