16 #define GETTEXT_DOMAIN "wesnoth-lib"
30 #include <boost/algorithm/string.hpp>
35 #define ERR_G LOG_STREAM(err, lg::general())
36 #define LOG_G LOG_STREAM(info, lg::general())
37 #define DBG_G LOG_STREAM(debug, lg::general())
38 #define ERR_CF LOG_STREAM(err, log_config)
47 const int TOUCH_MOUSE_INDEX = 255;
54 if(
mod_ & KMOD_CTRL) {
58 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
67 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
68 if(
mod_ & KMOD_SHIFT) {
72 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
81 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
87 if(other ==
nullptr) {
95 if(scopematch.none()) {
116 item[
"shift"] = !!(
mod_ & KMOD_SHIFT);
117 item[
"ctrl"] = !!(
mod_ & KMOD_CTRL);
118 item[
"cmd"] = !!(
mod_ & KMOD_GUI);
119 item[
"alt"] = !!(
mod_ & KMOD_ALT);
126 hotkey_ptr base = std::make_shared<hotkey_void>();
134 auto keyboard = std::make_shared<hotkey_keyboard>();
135 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
137 code =
event.key.keysym.sym;
138 keyboard->set_keycode(code);
139 keyboard->set_text(SDL_GetKeyName(event.key.keysym.sym));
143 case SDL_TEXTINPUT: {
147 auto keyboard = std::make_shared<hotkey_keyboard>();
148 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
149 std::string text = std::string(event.text.text);
150 keyboard->set_text(text);
151 if(text ==
":" || text ==
"`") {
152 mods = mods & ~KMOD_SHIFT;
156 case SDL_MOUSEBUTTONUP: {
157 auto mouse = std::make_shared<hotkey_mouse>();
158 base = std::dynamic_pointer_cast<hotkey_base>(mouse);
159 mouse->set_button(event.button.button);
164 ERR_G <<
"Trying to bind an unknown event type:" <<
event.type;
168 base->set_mods(mods);
169 base->set_command(
id);
170 base->unset_default();
177 hotkey_ptr base = std::make_shared<hotkey_void>();
180 if(!mouse_cfg.
empty()) {
181 auto mouse = std::make_shared<hotkey_mouse>();
182 base = std::dynamic_pointer_cast<hotkey_base>(mouse);
183 if(mouse_cfg.
to_int() == TOUCH_MOUSE_INDEX) {
184 mouse->set_button(TOUCH_MOUSE_INDEX);
186 mouse->set_button(cfg[
"button"].to_int());
190 const std::string& key_cfg = cfg[
"key"];
191 if(!key_cfg.empty()) {
192 auto keyboard = std::make_shared<hotkey_keyboard>();
193 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
195 SDL_Keycode keycode = SDL_GetKeyFromName(key_cfg.c_str());
196 if(keycode == SDLK_UNKNOWN) {
197 ERR_G <<
"Unknown key: " << key_cfg;
199 keyboard->set_text(key_cfg);
200 keyboard->set_keycode(keycode);
207 unsigned int mods = 0;
209 if(cfg[
"shift"].to_bool())
211 if(cfg[
"ctrl"].to_bool())
213 if(cfg[
"cmd"].to_bool())
215 if(cfg[
"alt"].to_bool())
218 base->set_mods(mods);
219 base->set_command(cfg[
"command"].str());
221 cfg[
"disabled"].to_bool() ? base->disable() : base->enable();
228 if(event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEBUTTONDOWN && event.type != SDL_FINGERDOWN
229 && event.type != SDL_FINGERUP) {
239 return button_ == TOUCH_MOUSE_INDEX;
242 return event.button.button ==
button_;
247 return "mouse " + std::to_string(
button_);
261 boost::algorithm::to_lower(
text_);
274 if((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
277 return event.key.keysym.sym ==
keycode_ && mods ==
mod_;
280 if(event.type == SDL_TEXTINPUT && !command.
toggle) {
281 std::string text = std::string(event.text.text);
282 boost::algorithm::to_lower(text);
283 if(text ==
":" || text ==
"`") {
284 mods = mods & ~KMOD_SHIFT;
294 auto other_m = std::dynamic_pointer_cast<hotkey_mouse>(other);
295 if(other_m ==
nullptr) {
299 return button_ == other_m->button_;
312 if(item->get_command() == command) {
321 auto other_k = std::dynamic_pointer_cast<hotkey_keyboard>(other);
322 if(other_k ==
nullptr) {
326 return text_ == other_k->text_;
332 auto iter = std::find_if(hotkeys_.begin(), hotkeys_.end(),
335 if(iter != hotkeys_.end()) {
338 hotkeys_.push_back(std::move(item));
346 if(item->get_command() == command) {
347 if(item->is_default()) {
364 if(item->matches(event)) {
368 return std::make_shared<hotkey_void>();
376 new_hotkeys.push_back(std::move(item));
380 default_hotkey_cfg_ = cfg;
381 hotkeys_.swap(new_hotkeys);
388 item->unset_default();
398 if(!default_hotkey_cfg_.child_range(
"hotkey").empty()) {
401 ERR_G <<
"no default hotkeys set yet; all hotkeys are now unassigned!";
415 if((!item->is_default() && item->active()) || (item->is_default() && item->is_disabled())) {
424 std::vector<std::string>
names;
426 if(item->get_command() ==
id && !item->null() && !item->is_disabled()) {
427 names.push_back(item->get_name());
433 names.push_back(
"escape");
434 }
else if(
id ==
"quit-to-desktop") {
436 names.push_back(
"cmd+q");
438 names.push_back(
"alt+F4");
447 if(event.type == SDL_JOYBUTTONUP || event.type == SDL_JOYHATMOTION || event.type == SDL_MOUSEBUTTONUP) {
453 if(mods & KMOD_CTRL || mods & KMOD_ALT || mods & KMOD_GUI) {
454 return event.type == SDL_KEYUP;
456 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.
std::string get_name() const
Return "name" of hotkey.
virtual bool bindings_equal(const hotkey_ptr &other)
Checks whether the hotkey bindings and scope are equal.
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 const std::string get_name_helper() const =0
This is invoked by hotkey_base::get_name and must be implemented by subclasses.
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).
bool is_touch(const SDL_MouseButtonEvent &event)
Check if this mouse button event is caused by a touch.
Keyboard shortcuts for game actions.
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
const hotkey_command & get_hotkey_command(std::string_view command)
Returns the hotkey_command with the given id.
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(std::string_view 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.