16 #define GETTEXT_DOMAIN "wesnoth-lib"
29 #include <boost/algorithm/string.hpp>
34 #define ERR_G LOG_STREAM(err, lg::general())
35 #define LOG_G LOG_STREAM(info, lg::general())
36 #define DBG_G LOG_STREAM(debug, lg::general())
37 #define ERR_CF LOG_STREAM(err, log_config)
46 const int TOUCH_MOUSE_INDEX = 255;
53 if(
mod_ & KMOD_CTRL) {
57 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
66 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
67 if(
mod_ & KMOD_SHIFT) {
71 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
80 ret += (!ret.empty() && !boost::algorithm::ends_with(ret,
"+") ?
"+" :
"");
86 if(other ==
nullptr) {
94 if(scopematch.none()) {
115 item[
"shift"] = !!(
mod_ & KMOD_SHIFT);
116 item[
"ctrl"] = !!(
mod_ & KMOD_CTRL);
117 item[
"cmd"] = !!(
mod_ & KMOD_GUI);
118 item[
"alt"] = !!(
mod_ & KMOD_ALT);
125 hotkey_ptr base = std::make_shared<hotkey_void>();
133 auto keyboard = std::make_shared<hotkey_keyboard>();
134 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
136 code =
event.key.keysym.sym;
137 keyboard->set_keycode(code);
138 keyboard->set_text(SDL_GetKeyName(event.key.keysym.sym));
142 case SDL_TEXTINPUT: {
146 auto keyboard = std::make_shared<hotkey_keyboard>();
147 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
148 std::string text = std::string(event.text.text);
149 keyboard->set_text(text);
150 if(text ==
":" || text ==
"`") {
151 mods = mods & ~KMOD_SHIFT;
155 case SDL_MOUSEBUTTONUP: {
156 auto mouse = std::make_shared<hotkey_mouse>();
157 base = std::dynamic_pointer_cast<hotkey_base>(mouse);
158 mouse->set_button(event.button.button);
163 ERR_G <<
"Trying to bind an unknown event type:" <<
event.type;
167 base->set_mods(mods);
168 base->set_command(
id);
169 base->unset_default();
176 hotkey_ptr base = std::make_shared<hotkey_void>();
179 if(!mouse_cfg.
empty()) {
180 auto mouse = std::make_shared<hotkey_mouse>();
181 base = std::dynamic_pointer_cast<hotkey_base>(mouse);
182 if(mouse_cfg.
to_int() == TOUCH_MOUSE_INDEX) {
183 mouse->set_button(TOUCH_MOUSE_INDEX);
185 mouse->set_button(cfg[
"button"].to_int());
189 const std::string& key_cfg = cfg[
"key"];
190 if(!key_cfg.empty()) {
191 auto keyboard = std::make_shared<hotkey_keyboard>();
192 base = std::dynamic_pointer_cast<hotkey_base>(keyboard);
194 SDL_Keycode keycode = SDL_GetKeyFromName(key_cfg.c_str());
195 if(keycode == SDLK_UNKNOWN) {
196 ERR_G <<
"Unknown key: " << key_cfg;
198 keyboard->set_text(key_cfg);
199 keyboard->set_keycode(keycode);
206 unsigned int mods = 0;
208 if(cfg[
"shift"].to_bool())
210 if(cfg[
"ctrl"].to_bool())
212 if(cfg[
"cmd"].to_bool())
214 if(cfg[
"alt"].to_bool())
217 base->set_mods(mods);
218 base->set_command(cfg[
"command"].str());
220 cfg[
"disabled"].to_bool() ? base->disable() : base->enable();
227 if(event.type != SDL_MOUSEBUTTONUP && event.type != SDL_MOUSEBUTTONDOWN && event.type != SDL_FINGERDOWN
228 && event.type != SDL_FINGERUP) {
237 if(event.button.which == SDL_TOUCH_MOUSEID) {
238 return button_ == TOUCH_MOUSE_INDEX;
241 return event.button.button ==
button_;
246 return "mouse " + std::to_string(
button_);
260 boost::algorithm::to_lower(
text_);
273 if((event.type == SDL_KEYDOWN || event.type == SDL_KEYUP)
276 return event.key.keysym.sym ==
keycode_ && mods ==
mod_;
279 if(event.type == SDL_TEXTINPUT && !command.
toggle) {
280 std::string text = std::string(event.text.text);
281 boost::algorithm::to_lower(text);
282 if(text ==
":" || text ==
"`") {
283 mods = mods & ~KMOD_SHIFT;
293 auto other_m = std::dynamic_pointer_cast<hotkey_mouse>(other);
294 if(other_m ==
nullptr) {
298 return button_ == other_m->button_;
311 if(item->get_command() == command) {
320 auto other_k = std::dynamic_pointer_cast<hotkey_keyboard>(other);
321 if(other_k ==
nullptr) {
325 return text_ == other_k->text_;
330 if(!hotkeys_.empty()) {
338 auto iter = std::find_if(hotkeys_.begin(), hotkeys_.end(),
341 if(iter != hotkeys_.end()) {
344 hotkeys_.push_back(std::move(item));
352 if(item->get_command() == command) {
353 if(item->is_default()) {
370 if(item->matches(event)) {
374 return std::make_shared<hotkey_void>();
382 new_hotkeys.push_back(std::move(item));
386 default_hotkey_cfg_ = cfg;
387 hotkeys_.swap(new_hotkeys);
394 item->unset_default();
404 if(!default_hotkey_cfg_.child_range(
"hotkey").empty()) {
407 ERR_G <<
"no default hotkeys set yet; all hotkeys are now unassigned!";
421 if((!item->is_default() && item->active()) || (item->is_default() && item->is_disabled())) {
430 std::vector<std::string>
names;
432 if(item->get_command() ==
id && !item->null() && !item->is_disabled()) {
433 names.push_back(item->get_name());
439 names.push_back(
"escape");
440 }
else if(
id ==
"quit-to-desktop") {
442 names.push_back(
"cmd+q");
444 names.push_back(
"alt+F4");
453 if(event.type == SDL_JOYBUTTONUP || event.type == SDL_JOYHATMOTION || event.type == SDL_MOUSEBUTTONUP) {
459 if(mods & KMOD_CTRL || mods & KMOD_ALT || mods & KMOD_GUI) {
460 return event.type == SDL_KEYUP;
462 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.
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.
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).
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
std::vector< hotkey::hotkey_ptr > hotkey_list
void del_hotkey(const hotkey_ptr &item)
Remove a hotkey from 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.
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::size_t erase(Container &container, const Value &value)
Convenience wrapper for using std::remove on a container.
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.