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) {
56 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
65 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
66 if(
mod_ & KMOD_SHIFT) {
70 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
79 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
85 if(other ==
nullptr) {
93 if(scopematch.none()) {
114 item[
"shift"] = !!(
mod_ & KMOD_SHIFT);
115 item[
"ctrl"] = !!(
mod_ & KMOD_CTRL);
124 hotkey_ptr base = std::make_shared<hotkey_void>();
132 auto keyboard = std::make_shared<hotkey_keyboard>();
133 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
135 code =
event.key.keysym.sym;
136 keyboard->set_keycode(code);
137 keyboard->set_text(SDL_GetKeyName(event.key.keysym.sym));
141 case SDL_TEXTINPUT: {
145 auto keyboard = std::make_shared<hotkey_keyboard>();
146 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
147 std::string text = std::string(event.text.text);
148 keyboard->set_text(text);
149 if(text ==
":" || text ==
"`") {
150 mods = mods & ~KMOD_SHIFT;
154 case SDL_MOUSEBUTTONUP: {
155 auto mouse = std::make_shared<hotkey_mouse>();
156 base = std::dynamic_pointer_cast<hotkey_base>(mouse);
157 mouse->set_button(event.button.button);
162 ERR_G <<
"Trying to bind an unknown event type:" <<
event.type;
166 base->set_mods(mods);
167 base->set_command(
id);
168 base->unset_default();
175 hotkey_ptr base = std::make_shared<hotkey_void>();
178 if(!mouse_cfg.
empty()) {
179 auto mouse = std::make_shared<hotkey_mouse>();
180 base = std::dynamic_pointer_cast<hotkey_base>(mouse);
181 if(mouse_cfg.
to_int() == TOUCH_MOUSE_INDEX) {
182 mouse->set_button(TOUCH_MOUSE_INDEX);
184 mouse->set_button(cfg[
"button"].to_int());
188 const std::string& key_cfg = cfg[
"key"];
189 if(!key_cfg.empty()) {
190 auto keyboard = std::make_shared<hotkey_keyboard>();
191 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
193 SDL_Keycode keycode = SDL_GetKeyFromName(key_cfg.c_str());
194 if(keycode == SDLK_UNKNOWN) {
195 ERR_G <<
"Unknown key: " << key_cfg;
197 keyboard->set_text(key_cfg);
198 keyboard->set_keycode(keycode);
205 unsigned int mods = 0;
207 if(cfg[
"shift"].to_bool())
209 if(cfg[
"ctrl"].to_bool())
211 if(cfg[
"cmd"].to_bool())
213 if(cfg[
"alt"].to_bool())
216 base->set_mods(mods);
217 base->set_command(cfg[
"command"].str());
219 cfg[
"disabled"].to_bool() ? base->disable() : base->enable();
226 if(event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEBUTTONDOWN && event.type != SDL_FINGERDOWN
227 && event.type != SDL_FINGERUP) {
236 if(event.button.which == SDL_TOUCH_MOUSEID) {
237 return button_ == TOUCH_MOUSE_INDEX;
240 return event.button.button ==
button_;
245 return "mouse " + std::to_string(
button_);
259 boost::algorithm::to_lower(
text_);
272 if((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
275 return event.key.keysym.sym ==
keycode_ && mods ==
mod_;
278 if(event.type == SDL_TEXTINPUT && !command.
toggle) {
279 std::string text = std::string(event.text.text);
280 boost::algorithm::to_lower(text);
281 if(text ==
":" || text ==
"`") {
282 mods = mods & ~KMOD_SHIFT;
292 auto other_m = std::dynamic_pointer_cast<hotkey_mouse>(other);
293 if(other_m ==
nullptr) {
297 return button_ == other_m->button_;
310 if(
item->get_command() == command) {
319 auto other_k = std::dynamic_pointer_cast<hotkey_keyboard>(other);
320 if(other_k ==
nullptr) {
324 return text_ == other_k->text_;
329 if(!hotkeys_.empty()) {
337 auto iter = std::find_if(hotkeys_.begin(), hotkeys_.end(),
340 if(iter != hotkeys_.end()) {
343 hotkeys_.push_back(std::move(
item));
351 if(
item->get_command() == command) {
352 if(
item->is_default()) {
369 if(
item->matches(event)) {
373 return std::make_shared<hotkey_void>();
381 new_hotkeys.push_back(std::move(
item));
385 default_hotkey_cfg_ = cfg;
386 hotkeys_.swap(new_hotkeys);
393 item->unset_default();
403 if(!default_hotkey_cfg_.child_range(
"hotkey").empty()) {
406 ERR_G <<
"no default hotkeys set yet; all hotkeys are now unassigned!";
420 if((!
item->is_default() &&
item->active()) || (
item->is_default() &&
item->is_disabled())) {
429 std::vector<std::string>
names;
431 if(
item->get_command() ==
id && !
item->null() && !
item->is_disabled()) {
438 names.push_back(
"escape");
439 }
else if(
id ==
"quit-to-desktop") {
441 names.push_back(
"cmd+q");
443 names.push_back(
"alt+F4");
452 if(event.type == SDL_JOYBUTTONUP || event.type == SDL_JOYHATMOTION || event.type == SDL_MOUSEBUTTONUP) {
458 if(mods & KMOD_CTRL || mods & KMOD_ALT || mods & KMOD_GUI) {
459 return event.type == SDL_KEYUP;
461 return event.type == SDL_TEXTINPUT ||
event.type == SDL_KEYUP;
std::vector< std::string > names
static bool is_uncomposable(const SDL_KeyboardEvent &event)
Variant for storing WML attributes.
int to_int(int def=0) const
bool empty() const
Tests for an attribute that either was never set or was set to "".
A config object defines a single node in a WML file, with access to child nodes.
void clear_children(T... keys)
config & add_child(config_key_type key)
A class grating read only view to a vector of config objects, viewed as one config with all children ...
config_array_view child_range(config_key_type key) const
virtual void save_helper(config &cfg) const =0
const std::string & get_command() const
Returns the string name of the HOTKEY_COMMAND.
void save(config &cfg) const
Save the hotkey into the configuration object.
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.
bool matches(const SDL_Event &event) const
Used to evaluate whether:
virtual bool bindings_equal(hotkey_ptr other)
Checks whether the hotkey bindings and scope are equal.
virtual const std::string get_name_helper() const =0
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
const std::string get_name() const
Return "name" of hotkey.
virtual bool matches_helper(const SDL_Event &event) const =0
This is invoked by hotkey_base::matches as a helper for the concrete classes.
void set_text(const std::string &text)
virtual void save_helper(config &cfg) const
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.
virtual const std::string get_name_helper() const
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
virtual void save_helper(config &cfg) const
virtual bool matches_helper(const SDL_Event &event) const
This is invoked by hotkey_base::matches as a helper for the concrete classes.
virtual bool bindings_equal_helper(hotkey_ptr other) const
This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
Definitions for the interface to Wesnoth Markup Language (WML).
static lg::log_domain log_config("config")
Standard logging facilities (interface).
void remove()
Removes a tip.
std::pair< std::string, unsigned > item
Keyboard shortcuts for game actions.
const hotkey_command & get_hotkey_command(const std::string &command)
returns the hotkey_command with the given name
const hotkey_list & get_hotkeys()
Returns the list of hotkeys.
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
void save_hotkeys(config &cfg)
Save the non-default hotkeys to the config.
std::shared_ptr< class hotkey_base > hotkey_ptr
bool has_hotkey_item(const std::string &command)
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...
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
void reset_default_hotkeys()
Reset all hotkeys to the defaults.
hotkey_ptr load_from_config(const config &cfg)
Create and instantiate a hotkey from a config element.
hotkey_ptr create_hotkey(const std::string &id, const SDL_Event &event)
Create a new hotkey item for a command from an SDL_Event.
std::bitset< SCOPE_COUNT > hk_scopes
void del_hotkey(hotkey_ptr item)
Remove a hotkey from the list of hotkeys.
std::vector< hotkey::hotkey_ptr > hotkey_list
void load_custom_hotkeys(const game_config_view &cfg)
Registers all hotkeys present in this config, overwriting any matching default hotkeys.
bool is_scope_active(scope s)
scope
Available hotkey scopes.
void load_default_hotkeys(const game_config_view &cfg)
Registers all hotkeys present in this config.
void add_hotkey(hotkey_ptr item)
Add a hotkey to the list of hotkeys.
bool is_hotkeyable_event(const SDL_Event &event)
unsigned get_mods()
Returns a bitmask of active modifier keys (ctrl, shift, alt, gui).
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
std::string join(const T &v, const std::string &s=",")
Generates a new string joining container items in a list.
This file contains object "key", which is used to store information about keys while annotation parsi...
Stores all information related to functions that can be bound to hotkeys.
bool toggle
Toggle hotkeys have some restrictions on what can be bound to them.
hk_scopes scope
The visibility scope of the command.