16 #define GETTEXT_DOMAIN "wesnoth-lib" 28 #include <boost/algorithm/string.hpp> 33 #define ERR_G LOG_STREAM(err, lg::general()) 34 #define LOG_G LOG_STREAM(info, lg::general()) 35 #define DBG_G LOG_STREAM(debug, lg::general()) 36 #define ERR_CF LOG_STREAM(err, log_config) 45 const int TOUCH_MOUSE_INDEX = 255;
52 if(
mod_ & KMOD_CTRL) {
62 if(
mod_ & KMOD_SHIFT) {
81 if(other ==
nullptr) {
89 if(scopematch.none()) {
110 item[
"shift"] = !!(
mod_ & KMOD_SHIFT);
111 item[
"ctrl"] = !!(
mod_ & KMOD_CTRL);
112 item[
"cmd"] = !!(
mod_ & KMOD_GUI);
113 item[
"alt"] = !!(
mod_ & KMOD_ALT);
120 hotkey_ptr base = std::make_shared<hotkey_void>();
128 auto keyboard = std::make_shared<hotkey_keyboard>();
129 base = std::dynamic_pointer_cast<
hotkey_base>(keyboard);
131 code =
event.key.keysym.sym;
132 keyboard->set_keycode(code);
133 keyboard->set_text(SDL_GetKeyName(event.key.keysym.sym));
137 case SDL_TEXTINPUT: {
141 auto keyboard = std::make_shared<hotkey_keyboard>();
142 base = std::dynamic_pointer_cast<
hotkey_base>(keyboard);
143 std::string text = std::string(event.text.text);
144 keyboard->set_text(text);
145 if(text ==
":" || text ==
"`") {
146 mods = mods & ~KMOD_SHIFT;
150 case SDL_MOUSEBUTTONUP: {
151 auto mouse = std::make_shared<hotkey_mouse>();
152 base = std::dynamic_pointer_cast<
hotkey_base>(mouse);
153 mouse->set_button(event.button.button);
158 ERR_G <<
"Trying to bind an unknown event type:" <<
event.type;
162 base->set_mods(mods);
163 base->set_command(
id);
164 base->unset_default();
171 hotkey_ptr base = std::make_shared<hotkey_void>();
174 if(!mouse_cfg.empty()) {
175 auto mouse = std::make_shared<hotkey_mouse>();
176 base = std::dynamic_pointer_cast<
hotkey_base>(mouse);
177 if(mouse_cfg.to_int() == TOUCH_MOUSE_INDEX) {
178 mouse->set_button(TOUCH_MOUSE_INDEX);
180 mouse->set_button(cfg[
"button"].to_int());
184 const std::string& key_cfg = cfg[
"key"];
185 if(!key_cfg.empty()) {
186 auto keyboard = std::make_shared<hotkey_keyboard>();
187 base = std::dynamic_pointer_cast<
hotkey_base>(keyboard);
189 SDL_Keycode keycode = SDL_GetKeyFromName(key_cfg.c_str());
190 if(keycode == SDLK_UNKNOWN) {
191 ERR_G <<
"Unknown key: " << key_cfg;
193 keyboard->set_text(key_cfg);
194 keyboard->set_keycode(keycode);
201 unsigned int mods = 0;
203 if(cfg[
"shift"].to_bool())
205 if(cfg[
"ctrl"].to_bool())
207 if(cfg[
"cmd"].to_bool())
209 if(cfg[
"alt"].to_bool())
212 base->set_mods(mods);
213 base->set_command(cfg[
"command"].str());
215 cfg[
"disabled"].to_bool() ? base->disable() : base->enable();
222 if(event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEBUTTONDOWN && event.type != SDL_FINGERDOWN
223 && event.type != SDL_FINGERUP) {
232 if(event.button.which == SDL_TOUCH_MOUSEID) {
233 return button_ == TOUCH_MOUSE_INDEX;
236 return event.button.button == button_;
241 return "mouse " + std::to_string(button_);
248 item[
"button"] = button_;
255 boost::algorithm::to_lower(text_);
268 if((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
271 return event.key.keysym.sym == keycode_ && mods ==
mod_;
274 if(event.type == SDL_TEXTINPUT && !command.
toggle) {
275 std::string text = std::string(event.text.text);
276 boost::algorithm::to_lower(text);
277 if(text ==
":" || text ==
"`") {
278 mods = mods & ~KMOD_SHIFT;
280 return text_ == text &&
utf8::size(std::string(event.text.text)) == 1 && mods ==
mod_;
288 auto other_m = std::dynamic_pointer_cast<
hotkey_mouse>(other);
289 if(other_m ==
nullptr) {
293 return button_ == other_m->
button_;
306 if(
item->get_command() == command) {
316 if(other_k ==
nullptr) {
320 return text_ == other_k->
text_;
325 if(!hotkeys_.empty()) {
333 auto iter = std::find_if(hotkeys_.begin(), hotkeys_.end(),
336 if(iter != hotkeys_.end()) {
339 hotkeys_.push_back(std::move(item));
347 if(
item->get_command() == command) {
348 if(
item->is_default()) {
365 if(
item->matches(event)) {
369 return std::make_shared<hotkey_void>();
377 new_hotkeys.push_back(std::move(
item));
381 default_hotkey_cfg_ = cfg;
382 hotkeys_.swap(new_hotkeys);
389 item->unset_default();
399 if(!default_hotkey_cfg_.child_range(
"hotkey").empty()) {
402 ERR_G <<
"no default hotkeys set yet; all hotkeys are now unassigned!";
416 if((!
item->is_default() &&
item->active()) || (
item->is_default() &&
item->is_disabled())) {
425 std::vector<std::string>
names;
427 if(
item->get_command() ==
id && !
item->null() && !
item->is_disabled()) {
428 names.push_back(
item->get_name());
434 names.push_back(
"escape");
435 }
else if(
id ==
"quit-to-desktop") {
437 names.push_back(
"cmd+q");
439 names.push_back(
"alt+F4");
448 if(event.type == SDL_JOYBUTTONUP || event.type == SDL_JOYHATMOTION || event.type == SDL_MOUSEBUTTONUP) {
454 if(mods & KMOD_CTRL || mods & KMOD_ALT || mods & KMOD_GUI) {
455 return event.type == SDL_KEYUP;
457 return event.type == SDL_TEXTINPUT ||
event.type == SDL_KEYUP;
void remove()
Removes a tip.
virtual bool matches_helper(const SDL_Event &event) const
This is invoked by hotkey_base::matches as a helper for the concrete classes.
virtual void save_helper(config &cfg) const
void clear_children(T... keys)
hotkey_ptr load_from_config(const config &cfg)
Create and instantiate a hotkey from a config element.
void save_hotkeys(config &cfg)
Save the non-default hotkeys to the config.
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
bool is_scope_active(scope s)
Variant for storing WML attributes.
scope
Available hotkey scopes.
const std::string get_name() const
Return "name" of hotkey.
config_array_view child_range(config_key_type key) const
bool ends_with(const std::string &str, const std::string &suffix)
virtual void save_helper(config &cfg) const
virtual bool bindings_equal_helper(hotkey_ptr other) const =0
This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
static lg::log_domain log_config("config")
void del_hotkey(hotkey_ptr item)
Remove a hotkey from the list of hotkeys.
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
unsigned get_mods()
Returns a bitmask of active modifier keys (ctrl, shift, alt, gui).
Stores all information related to functions that can be bound to hotkeys.
bool has_hotkey_item(const std::string &command)
bool matches(const SDL_Event &event) const
Used to evaluate whether:
const std::string & get_command() const
Returns the string name of the HOTKEY_COMMAND.
virtual const std::string get_name_helper() const
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
static bool is_uncomposable(const SDL_KeyboardEvent &event)
Definitions for the interface to Wesnoth Markup Language (WML).
virtual bool matches_helper(const SDL_Event &event) const =0
This is invoked by hotkey_base::matches as a helper for the concrete classes.
Keyboard shortcuts for game actions.
const hotkey_list & get_hotkeys()
Returns the list of hotkeys.
void load_custom_hotkeys(const game_config_view &cfg)
Registers all hotkeys present in this config, overwriting any matching default hotkeys.
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
void set_text(const std::string &text)
std::bitset< SCOPE_COUNT > hk_scopes
virtual void save_helper(config &cfg) const =0
const hotkey_ptr get_hotkey(const SDL_Event &event)
Iterate through the list of hotkeys and return a hotkey that matches the SDL_Event and the current ke...
std::shared_ptr< class hotkey_base > hotkey_ptr
virtual const std::string get_name_helper() const
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
virtual bool bindings_equal_helper(hotkey_ptr other) const
This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
virtual bool matches_helper(const SDL_Event &event) const
This is invoked by hotkey_base::matches as a helper for the concrete classes.
std::vector< hotkey::hotkey_ptr > hotkey_list
hk_scopes scope
The visibility scope of the command.
void save(config &cfg) const
Save the hotkey into the configuration object.
bool toggle
Toggle hotkeys have some restrictions on what can be bound to them.
std::vector< std::string > names
virtual const std::string get_name_helper() const =0
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
void add_hotkey(hotkey_ptr item)
Add a hotkey to the list of hotkeys.
void reset_default_hotkeys()
Reset all hotkeys to the defaults.
config & add_child(config_key_type key)
This class is responsible for handling mouse button presses.
This is the base class for hotkey event matching.
This class is responsible for handling keys, not modifiers.
hotkey_ptr create_hotkey(const std::string &id, const SDL_Event &event)
Create a new hotkey item for a command from an SDL_Event.
Standard logging facilities (interface).
void load_default_hotkeys(const game_config_view &cfg)
Registers all hotkeys present in this config.
virtual bool bindings_equal(hotkey_ptr other)
Checks whether the hotkey bindings and scope are equal.
bool is_hotkeyable_event(const SDL_Event &event)
A config object defines a single node in a WML file, with access to child nodes.
const hotkey_command & get_hotkey_command(const std::string &command)
returns the hotkey_command with the given name
virtual bool bindings_equal_helper(hotkey_ptr other) const
This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
std::pair< std::string, unsigned > item