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);
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_);
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;
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) {
315 auto other_k = std::dynamic_pointer_cast<hotkey_keyboard>(other);
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()) {
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;
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.
static lg::log_domain log_config("config")
Standard logging facilities (interface).
bool ends_with(const std::string &str, const std::string &suffix)
void remove()
Removes a tip.
std::pair< std::string, unsigned > item
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
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.
const hotkey_command & get_hotkey_command(const std::string &command)
returns the hotkey_command with the given name
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.