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);
160 mouse->set_clicks(event.button.clicks);
165 ERR_G <<
"Trying to bind an unknown event type:" <<
event.type;
169 base->set_mods(mods);
170 base->set_command(
id);
171 base->unset_default();
178 hotkey_ptr base = std::make_shared<hotkey_void>();
181 if(!mouse_cfg.
empty()) {
182 auto mouse = std::make_shared<hotkey_mouse>();
183 base = std::dynamic_pointer_cast<hotkey_base>(mouse);
185 if(mouse_cfg.
to_int() == TOUCH_MOUSE_INDEX) {
186 mouse->set_button(TOUCH_MOUSE_INDEX);
188 mouse->set_button(
cfg[
"button"].to_int());
191 if(!
cfg[
"click"].empty()) {
192 mouse->set_clicks(
cfg[
"click"].to_int(1));
196 const std::string& key_cfg =
cfg[
"key"];
197 if(!key_cfg.empty()) {
198 auto keyboard = std::make_shared<hotkey_keyboard>();
199 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
201 SDL_Keycode keycode = SDL_GetKeyFromName(key_cfg.c_str());
202 if(keycode == SDLK_UNKNOWN) {
203 ERR_G <<
"Unknown key: " << key_cfg;
205 keyboard->set_text(key_cfg);
206 keyboard->set_keycode(keycode);
213 unsigned int mods = 0;
215 if(
cfg[
"shift"].to_bool())
217 if(
cfg[
"ctrl"].to_bool())
219 if(
cfg[
"cmd"].to_bool())
221 if(
cfg[
"alt"].to_bool())
224 base->set_mods(mods);
225 base->set_command(
cfg[
"command"].str());
227 cfg[
"disabled"].to_bool() ? base->disable() : base->enable();
235 case SDL_MOUSEBUTTONUP:
236 case SDL_MOUSEBUTTONDOWN:
250 return button_ == TOUCH_MOUSE_INDEX &&
clicks_ ==
event.button.clicks;
253 return event.button.button ==
button_;
258 std::stringstream hotkey_name;
260 case SDL_BUTTON_LEFT:
261 hotkey_name <<
"left mouse";
263 case SDL_BUTTON_RIGHT:
264 hotkey_name <<
"right mouse";
266 case SDL_BUTTON_MIDDLE:
267 hotkey_name <<
"middle mouse";
270 hotkey_name <<
"mouse back";
273 hotkey_name <<
"mouse forward";
275 case TOUCH_MOUSE_INDEX:
276 hotkey_name <<
"touch";
279 hotkey_name <<
"mouse " + std::to_string(
button_);
283 hotkey_name <<
" (clicks: " <<
clicks_ <<
")";
286 return hotkey_name.str();
300 boost::algorithm::to_lower(
text_);
313 if((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
316 return event.key.keysym.sym ==
keycode_ && mods ==
mod_;
319 if(event.type == SDL_TEXTINPUT && !command.
toggle) {
320 std::string text = std::string(event.text.text);
321 boost::algorithm::to_lower(text);
322 if(text ==
":" || text ==
"`") {
323 mods = mods & ~KMOD_SHIFT;
333 auto other_m = std::dynamic_pointer_cast<hotkey_mouse>(other);
334 if(other_m ==
nullptr) {
338 return button_ == other_m->button_;
351 if(item->get_command() == command) {
360 auto other_k = std::dynamic_pointer_cast<hotkey_keyboard>(other);
361 if(other_k ==
nullptr) {
365 return text_ == other_k->text_;
371 auto iter = std::find_if(hotkeys_.begin(), hotkeys_.end(),
374 if(iter != hotkeys_.end()) {
377 hotkeys_.push_back(std::move(item));
385 if(item->get_command() == command) {
386 if(item->is_default()) {
403 if(item->matches(event)) {
407 return std::make_shared<hotkey_void>();
415 new_hotkeys.push_back(std::move(item));
419 default_hotkey_cfg_ =
cfg;
420 hotkeys_.
swap(new_hotkeys);
427 item->unset_default();
437 if(!default_hotkey_cfg_.child_range(
"hotkey").empty()) {
440 ERR_G <<
"no default hotkeys set yet; all hotkeys are now unassigned!";
454 if((!item->is_default() && item->active()) || (item->is_default() && item->is_disabled())) {
463 std::vector<std::string>
names;
465 if(item->get_command() ==
id && !item->null() && !item->is_disabled()) {
466 names.push_back(item->get_name());
472 names.push_back(
"escape");
473 }
else if(
id ==
"quit-to-desktop") {
475 names.push_back(
"cmd+q");
477 names.push_back(
"alt+F4");
486 if(event.type == SDL_JOYBUTTONUP || event.type == SDL_JOYHATMOTION || event.type == SDL_MOUSEBUTTONUP) {
492 if(mods & KMOD_CTRL || mods & KMOD_ALT || mods & KMOD_GUI) {
493 return event.type == SDL_KEYUP;
495 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)
child_itors child_range(config_key_type key)
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 ...
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.