This reworks the hotkey system to rely on keycodes.
There is a new class introduced, hokey_base, that is the public interface to the hotkey bindings. It is an abstract class that relies on concrete classes hokey_keyboard and hotkey_mouse to do the device specific hotkey work via the template method pattern. There are two factory methods introduced, load_hotkey and create_hotkey that should only be used to instantiate new objects. This commit also changes the hotkey ":" and "+" to ";" respective "=" becausse ":" and "+" are not valid keycodes.
This commit is contained in:
parent
a55bc98630
commit
2459e7db10
14 changed files with 1741 additions and 695 deletions
|
@ -66,7 +66,7 @@
|
|||
[/hotkey]
|
||||
[hotkey]
|
||||
command=command
|
||||
key=:
|
||||
key=;
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=continue
|
||||
|
@ -262,7 +262,7 @@
|
|||
[/hotkey]
|
||||
[hotkey]
|
||||
command=zoomin
|
||||
key="+"
|
||||
key="="
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=zoomout
|
||||
|
@ -293,11 +293,11 @@
|
|||
[/hotkey]
|
||||
[hotkey]
|
||||
command=wbbumpupaction
|
||||
key="page up"
|
||||
key="PageUp"
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=wbbumpdownaction
|
||||
key="page down"
|
||||
key="PageDown"
|
||||
[/hotkey]
|
||||
[hotkey]
|
||||
command=wbsupposedead
|
||||
|
|
|
@ -443,6 +443,7 @@ set(wesnoth-sdl_SRC
|
|||
sdl/window.cpp
|
||||
sdl/utils.cpp
|
||||
sdl/shader.cpp
|
||||
sdl/keyboard.cpp
|
||||
xBRZ/xbrz.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -166,6 +166,7 @@ libwesnoth_sdl_sources = Split("""
|
|||
sdl/exception.cpp
|
||||
sdl/rect.cpp
|
||||
sdl/image.cpp
|
||||
sdl/keyboard.cpp
|
||||
sdl/window.cpp
|
||||
tracer.cpp
|
||||
xBRZ/xbrz.cpp
|
||||
|
|
|
@ -56,7 +56,7 @@ void controller_base::handle_event(const SDL_Event& event)
|
|||
// in which case the key press events should go only to it.
|
||||
if(have_keyboard_focus()) {
|
||||
process_keydown_event(event);
|
||||
hotkey::key_event(get_display(), event.key, get_hotkey_command_executor());
|
||||
hotkey::key_event(get_display(), event, get_hotkey_command_executor());
|
||||
} else {
|
||||
process_focus_keydown_event(event);
|
||||
break;
|
||||
|
@ -67,11 +67,11 @@ void controller_base::handle_event(const SDL_Event& event)
|
|||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
process_keydown_event(event);
|
||||
hotkey::jbutton_event(get_display(), event.jbutton, get_hotkey_command_executor());
|
||||
hotkey::jbutton_event(get_display(), event, get_hotkey_command_executor());
|
||||
break;
|
||||
case SDL_JOYHATMOTION:
|
||||
process_keydown_event(event);
|
||||
hotkey::jhat_event(get_display(), event.jhat, get_hotkey_command_executor());
|
||||
hotkey::jhat_event(get_display(), event, get_hotkey_command_executor());
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
// Ignore old mouse motion events in the event queue
|
||||
|
@ -91,7 +91,7 @@ void controller_base::handle_event(const SDL_Event& event)
|
|||
if (get_mouse_handler_base().get_show_menu()){
|
||||
show_menu(get_display().get_theme().context_menu()->items(),event.button.x,event.button.y,true, get_display());
|
||||
}
|
||||
hotkey::mbutton_event(get_display(), event.button, get_hotkey_command_executor());
|
||||
hotkey::mbutton_event(get_display(), event, get_hotkey_command_executor());
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
get_mouse_handler_base().mouse_press(event.button, is_browsing());
|
||||
|
|
|
@ -220,7 +220,7 @@ private:
|
|||
*
|
||||
* @param event The SDL joystick hat event triggered.
|
||||
*/
|
||||
void hat_motion(const SDL_JoyHatEvent& event);
|
||||
void hat_motion(const SDL_Event& event);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -228,7 +228,7 @@ private:
|
|||
*
|
||||
* @param event The SDL joystick button event triggered.
|
||||
*/
|
||||
void button_down(const SDL_JoyButtonEvent& event);
|
||||
void button_down(const SDL_Event& event);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -236,7 +236,7 @@ private:
|
|||
*
|
||||
* @param event The SDL keyboard event triggered.
|
||||
*/
|
||||
void key_down(const SDL_KeyboardEvent& event);
|
||||
void key_down(const SDL_Event& event);
|
||||
|
||||
/**
|
||||
* Handles the pressing of a hotkey.
|
||||
|
@ -245,7 +245,7 @@ private:
|
|||
*
|
||||
* @returns True if the hotkey is handled false otherwise.
|
||||
*/
|
||||
bool hotkey_pressed(const hotkey::hotkey_item& key);
|
||||
bool hotkey_pressed(const hotkey::hotkey_ptr key);
|
||||
|
||||
/**
|
||||
* Fires a key down event.
|
||||
|
@ -372,7 +372,7 @@ void thandler::handle_event(const SDL_Event& event)
|
|||
} break;
|
||||
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
button_down(event.jbutton);
|
||||
button_down(event);
|
||||
break;
|
||||
|
||||
case SDL_JOYBUTTONUP:
|
||||
|
@ -382,11 +382,11 @@ void thandler::handle_event(const SDL_Event& event)
|
|||
break;
|
||||
|
||||
case SDL_JOYHATMOTION:
|
||||
hat_motion(event.jhat);
|
||||
hat_motion(event);
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
key_down(event.key);
|
||||
key_down(event);
|
||||
break;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
@ -689,11 +689,11 @@ tdispatcher* thandler::keyboard_dispatcher()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void thandler::hat_motion(const SDL_JoyHatEvent& event)
|
||||
void thandler::hat_motion(const SDL_Event& event)
|
||||
{
|
||||
const hotkey::hotkey_item& hk = hotkey::get_hotkey(event);
|
||||
const hotkey::hotkey_ptr& hk = hotkey::get_hotkey(event);
|
||||
bool done = false;
|
||||
if(!hk.null()) {
|
||||
if(!hk->null()) {
|
||||
done = hotkey_pressed(hk);
|
||||
}
|
||||
if(!done) {
|
||||
|
@ -702,11 +702,11 @@ void thandler::hat_motion(const SDL_JoyHatEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
void thandler::button_down(const SDL_JoyButtonEvent& event)
|
||||
void thandler::button_down(const SDL_Event& event)
|
||||
{
|
||||
const hotkey::hotkey_item& hk = hotkey::get_hotkey(event);
|
||||
const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
|
||||
bool done = false;
|
||||
if(!hk.null()) {
|
||||
if(!hk->null()) {
|
||||
done = hotkey_pressed(hk);
|
||||
}
|
||||
if(!done) {
|
||||
|
@ -715,22 +715,22 @@ void thandler::button_down(const SDL_JoyButtonEvent& event)
|
|||
}
|
||||
}
|
||||
|
||||
void thandler::key_down(const SDL_KeyboardEvent& event)
|
||||
void thandler::key_down(const SDL_Event& event)
|
||||
{
|
||||
const hotkey::hotkey_item& hk = hotkey::get_hotkey(event);
|
||||
const hotkey::hotkey_ptr hk = hotkey::get_hotkey(event);
|
||||
bool done = false;
|
||||
if(!hk.null()) {
|
||||
if(!hk->null()) {
|
||||
done = hotkey_pressed(hk);
|
||||
}
|
||||
if(!done) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
key_down(event.keysym.sym,
|
||||
static_cast<const SDL_Keymod>(event.keysym.mod),
|
||||
key_down(event.key.keysym.sym,
|
||||
static_cast<const SDL_Keymod>(event.key.keysym.mod),
|
||||
"");
|
||||
#else
|
||||
key_down(event.keysym.sym,
|
||||
event.keysym.mod,
|
||||
unicode_cast<std::string>(static_cast<ucs4::char_t>(event.keysym.unicode)));
|
||||
key_down(event.key.keysym.sym,
|
||||
event.key.keysym.mod,
|
||||
unicode_cast<std::string>(static_cast<ucs4::char_t>(event.key.keysym.unicode)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -740,7 +740,7 @@ void thandler::text_input(const std::string& unicode)
|
|||
key_down(static_cast<SDLKey>(0), static_cast<SDLMod>(0), unicode);
|
||||
}
|
||||
|
||||
bool thandler::hotkey_pressed(const hotkey::hotkey_item& key)
|
||||
bool thandler::hotkey_pressed(const hotkey::hotkey_ptr key)
|
||||
{
|
||||
tdispatcher* dispatcher = keyboard_dispatcher();
|
||||
|
||||
|
@ -748,7 +748,7 @@ bool thandler::hotkey_pressed(const hotkey::hotkey_item& key)
|
|||
return false;
|
||||
}
|
||||
|
||||
return dispatcher->execute_hotkey(hotkey::get_id(key.get_command()));
|
||||
return dispatcher->execute_hotkey(hotkey::get_id(key->get_command()));
|
||||
}
|
||||
|
||||
void thandler::key_down(const SDLKey key,
|
||||
|
|
|
@ -43,10 +43,7 @@ static lg::log_domain log_config("config");
|
|||
|
||||
namespace hotkey {
|
||||
|
||||
static void key_event_execute(display& disp, const SDL_KeyboardEvent& event, command_executor* executor);
|
||||
static void jbutton_event_execute(display& disp, const SDL_JoyButtonEvent& event, command_executor* executor);
|
||||
static void jhat_event_execute(display& disp, const SDL_JoyHatEvent& event, command_executor* executor);
|
||||
static void mbutton_event_execute(display& disp, const SDL_MouseButtonEvent& event, command_executor* executor);
|
||||
static void event_execute(display& disp, const SDL_Event& event, command_executor* executor);
|
||||
|
||||
bool command_executor::execute_command(const hotkey_command& cmd, int /*index*/)
|
||||
{
|
||||
|
@ -480,47 +477,47 @@ void basic_handler::handle_event(const SDL_Event& event)
|
|||
// handled by the executor.
|
||||
// If we're not in a dialog we can call the regular key event handler.
|
||||
if (!gui::in_dialog()) {
|
||||
key_event(*disp_, event.key,exec_);
|
||||
key_event(*disp_, event,exec_);
|
||||
} else if (exec_ != NULL) {
|
||||
key_event_execute(*disp_, event.key,exec_);
|
||||
event_execute(*disp_, event,exec_);
|
||||
}
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
if (!gui::in_dialog()) {
|
||||
jbutton_event(*disp_, event.jbutton,exec_);
|
||||
jbutton_event(*disp_, event,exec_);
|
||||
} else if (exec_ != NULL) {
|
||||
jbutton_event_execute(*disp_, event.jbutton,exec_);
|
||||
event_execute(*disp_, event,exec_);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (!gui::in_dialog()) {
|
||||
mbutton_event(*disp_, event.button,exec_);
|
||||
mbutton_event(*disp_, event,exec_);
|
||||
} else if (exec_ != NULL) {
|
||||
mbutton_event_execute(*disp_, event.button,exec_);
|
||||
event_execute(*disp_, event,exec_);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mbutton_event(display& disp, const SDL_MouseButtonEvent& event, command_executor* executor)
|
||||
void mbutton_event(display& disp, const SDL_Event& event, command_executor* executor)
|
||||
{
|
||||
mbutton_event_execute(disp, event, executor);
|
||||
event_execute(disp, event, executor);
|
||||
}
|
||||
|
||||
void jbutton_event(display& disp, const SDL_JoyButtonEvent& event, command_executor* executor)
|
||||
void jbutton_event(display& disp, const SDL_Event& event, command_executor* executor)
|
||||
{
|
||||
jbutton_event_execute(disp, event, executor);
|
||||
event_execute(disp, event, executor);
|
||||
}
|
||||
|
||||
void jhat_event(display& disp, const SDL_JoyHatEvent& event, command_executor* executor)
|
||||
void jhat_event(display& disp, const SDL_Event& event, command_executor* executor)
|
||||
{
|
||||
jhat_event_execute(disp, event, executor);
|
||||
event_execute(disp, event, executor);
|
||||
}
|
||||
|
||||
void key_event(display& disp, const SDL_KeyboardEvent& event, command_executor* executor)
|
||||
void key_event(display& disp, const SDL_Event& event, command_executor* executor)
|
||||
{
|
||||
if (!executor) return;
|
||||
if(event.keysym.sym == SDLK_ESCAPE && disp.in_game()) {
|
||||
if(event.key.keysym.sym == SDLK_ESCAPE && disp.in_game()) {
|
||||
LOG_G << "escape pressed..showing quit\n";
|
||||
const int res = gui2::show_message(disp.video(), _("Quit"),
|
||||
_("Do you really want to quit?"), gui2::tmessage::yes_no_buttons);
|
||||
|
@ -531,13 +528,13 @@ void key_event(display& disp, const SDL_KeyboardEvent& event, command_executor*
|
|||
}
|
||||
}
|
||||
|
||||
key_event_execute(disp, event,executor);
|
||||
event_execute(disp, event,executor);
|
||||
}
|
||||
|
||||
void mbutton_event_execute(display& disp, const SDL_MouseButtonEvent& event, command_executor* executor)
|
||||
static void event_execute(display& disp, const SDL_Event& event, command_executor* executor)
|
||||
{
|
||||
if (!executor) return;
|
||||
const hotkey_item* hk = &get_hotkey(event);
|
||||
const hotkey_ptr hk = get_hotkey(event);
|
||||
if (!hk->active()) {
|
||||
return;
|
||||
}
|
||||
|
@ -546,52 +543,6 @@ void mbutton_event_execute(display& disp, const SDL_MouseButtonEvent& event, com
|
|||
executor->set_button_state(disp);
|
||||
}
|
||||
|
||||
void jbutton_event_execute(display& disp, const SDL_JoyButtonEvent& event, command_executor* executor)
|
||||
{
|
||||
if (!executor) return;
|
||||
const hotkey_item* hk = &get_hotkey(event);
|
||||
if (!hk->active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
execute_command(disp, get_hotkey_command(hk->get_command()), executor);
|
||||
executor->set_button_state(disp);
|
||||
}
|
||||
|
||||
void jhat_event_execute(display& disp, const SDL_JoyHatEvent& event, command_executor* executor)
|
||||
{
|
||||
if (!executor) return;
|
||||
const hotkey_item* hk = &get_hotkey(event);
|
||||
if (!hk->active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
execute_command(disp, get_hotkey_command(hk->get_command()), executor);
|
||||
executor->set_button_state(disp);
|
||||
}
|
||||
|
||||
void key_event_execute(display& disp, const SDL_KeyboardEvent& event, command_executor* executor)
|
||||
{
|
||||
if (!executor) return;
|
||||
const hotkey_item* hk = &get_hotkey(event);
|
||||
|
||||
#if 0
|
||||
// This is not generally possible without knowing keyboard layout.
|
||||
if (hk->null()) {
|
||||
//no matching hotkey was found, but try an in-exact match.
|
||||
hk = &get_hotkey(event, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!hk->active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
execute_command(disp, get_hotkey_command(hk->get_command()), executor);
|
||||
executor->set_button_state(disp);
|
||||
}
|
||||
|
||||
|
||||
void execute_command(display& disp, const hotkey_command& command, command_executor* executor, int index)
|
||||
{
|
||||
const int zoom_amount = 4;
|
||||
|
|
|
@ -133,10 +133,11 @@ public:
|
|||
* Also handles some events in the function itself,
|
||||
* and so is still meaningful to call with executor=NULL
|
||||
*/
|
||||
void jbutton_event(display& disp, const SDL_JoyButtonEvent& event, command_executor* executor);
|
||||
void jhat_event(display& disp, const SDL_JoyHatEvent& event, command_executor* executor);
|
||||
void key_event(display& disp, const SDL_KeyboardEvent& event, command_executor* executor);
|
||||
void mbutton_event(display& disp, const SDL_MouseButtonEvent& event, command_executor* executor);
|
||||
void jbutton_event(display& disp, const SDL_Event& event, command_executor* executor);
|
||||
void jhat_event(display& disp, const SDL_Event& event, command_executor* executor);
|
||||
void key_event(display& disp, const SDL_Event& event, command_executor* executor);
|
||||
void mbutton_event(display& disp, const SDL_Event& event, command_executor* executor);
|
||||
|
||||
|
||||
//TODO
|
||||
void execute_command(display& disp, const hotkey_command& command, command_executor* executor, int index=-1);
|
||||
|
|
|
@ -389,9 +389,9 @@ void add_wml_hotkey(const std::string& id, const t_string& description, const co
|
|||
|
||||
if(!default_hotkey.empty() && !has_hotkey_item(id))
|
||||
{
|
||||
hotkey_item new_item(default_hotkey, true);
|
||||
new_item.set_command(id);
|
||||
if(new_item.valid())
|
||||
hotkey::hotkey_ptr new_item = hotkey::load_from_config(default_hotkey);
|
||||
new_item->set_command(id);
|
||||
if(new_item->valid())
|
||||
{
|
||||
DBG_G << "added default description for the wml hotkey with id=" + id;
|
||||
add_hotkey(new_item);
|
||||
|
|
|
@ -24,243 +24,347 @@
|
|||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include "key.hpp"
|
||||
|
||||
#include "SDL.h"
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
#include "sdl/keyboard.hpp"
|
||||
#endif
|
||||
|
||||
static lg::log_domain log_config("config");
|
||||
#define ERR_G LOG_STREAM(err, lg::general)
|
||||
#define LOG_G LOG_STREAM(info, lg::general)
|
||||
#define DBG_G LOG_STREAM(debug, lg::general)
|
||||
#define ERR_CF LOG_STREAM(err, log_config)
|
||||
|
||||
namespace {
|
||||
|
||||
std::vector<hotkey::hotkey_item> hotkeys_;
|
||||
config default_hotkey_cfg_;
|
||||
|
||||
hotkey::hotkey_item null_hotkey_("null");
|
||||
|
||||
hotkey::hotkey_item& get_hotkey(int mouse, int joystick, int button, int hat, int value,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
{
|
||||
std::vector<hotkey::hotkey_item>::iterator itor;
|
||||
|
||||
for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
|
||||
|
||||
if ( !( hotkey::is_scope_active(hotkey::get_hotkey_command(itor->get_command()).scope) && itor->active() ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( itor->get_shift() != shift || itor->get_ctrl() != ctrl
|
||||
|| itor->get_cmd() != cmd || itor->get_alt() != alt ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( itor->get_joystick() == joystick && itor->get_button() == button
|
||||
&& itor->get_hat() == hat && itor->get_value() == value
|
||||
&& itor->get_mouse() == mouse ) {
|
||||
return *itor;
|
||||
}
|
||||
}
|
||||
|
||||
return null_hotkey_;
|
||||
}
|
||||
|
||||
hotkey::hotkey_item& get_hotkey(int character, int keycode,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
{
|
||||
std::vector<hotkey::hotkey_item>::iterator itor;
|
||||
|
||||
DBG_G << "getting hotkey: char=" << lexical_cast<std::string>(character)
|
||||
<< " keycode=" << lexical_cast<std::string>(keycode) << " "
|
||||
<< (shift ? "shift," : "")
|
||||
<< (ctrl ? "ctrl," : "")
|
||||
<< (cmd ? "cmd," : "")
|
||||
<< (alt ? "alt," : "")
|
||||
<< "\n";
|
||||
|
||||
// Sometimes control modifies by -64, ie ^A == 1.
|
||||
if (0 < character && character < 64 && ctrl) {
|
||||
if (shift) {
|
||||
character += 64;
|
||||
} else {
|
||||
character += 96;
|
||||
}
|
||||
/// @todo
|
||||
DBG_G << "Mapped to character " << lexical_cast<std::string>(character) << "\n";
|
||||
}
|
||||
|
||||
// For some reason on Mac OS, if cmd and shift are down, the character doesn't get upper-cased
|
||||
if (cmd && character > 96 && character < 123 && shift) {
|
||||
character -= 32; }
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (itor = hotkeys_.begin(); itor != hotkeys_.end(); ++itor) {
|
||||
// Special case for Ctrl+Return/Enter keys, which gets resolved to Ctrl-j and Ctrl-m characters (LF and CR respectively).
|
||||
// In such cases, do not match by character but go straight to key code.
|
||||
if (itor->get_character() != -1 &&
|
||||
!(tolower(character) == 'j' && keycode != SDLK_j) &&
|
||||
!(tolower(character) == 'm' && keycode != SDLK_m)) {
|
||||
if (character == itor->get_character()) {
|
||||
if (ctrl == itor->get_ctrl()
|
||||
&& cmd == itor->get_cmd()
|
||||
&& alt == itor->get_alt()) {
|
||||
if (hotkey::is_scope_active(hotkey::get_hotkey_command(itor->get_command()).scope) && itor->active()) {
|
||||
DBG_G << "Could match by character..." << "yes\n";
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
DBG_G << "Could match by character..." << "yes, but scope is inactive\n";
|
||||
}
|
||||
}
|
||||
DBG_G << "Could match by character..." << "but modifiers different\n";
|
||||
}
|
||||
} else if (itor->get_keycode() != -1) {
|
||||
if (keycode == itor->get_keycode()) {
|
||||
if (shift == itor->get_shift()
|
||||
&& ctrl == itor->get_ctrl()
|
||||
&& cmd == itor->get_cmd()
|
||||
&& alt == itor->get_alt()) {
|
||||
if (hotkey::is_scope_active(hotkey::get_hotkey_command(itor->get_command()).scope) && itor->active()) {
|
||||
DBG_G << "Could match by keycode..." << "yes\n";
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
DBG_G << "Could match by keycode..." << "yes, but scope is inactive\n";
|
||||
}
|
||||
}
|
||||
DBG_G << "Could match by keycode..." << "but modifiers different\n";
|
||||
}
|
||||
}
|
||||
if (found) { break; }
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return null_hotkey_; }
|
||||
|
||||
return *itor;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace hotkey {
|
||||
|
||||
hotkey_list hotkeys_;
|
||||
config default_hotkey_cfg_;
|
||||
|
||||
const hotkey_item& get_hotkey(const SDL_JoyButtonEvent& event)
|
||||
static unsigned int sdl_get_mods()
|
||||
{
|
||||
CKey keystate;
|
||||
bool shift = keystate[SDLK_RSHIFT] || keystate[SDLK_LSHIFT];
|
||||
bool ctrl = keystate[SDLK_RCTRL] || keystate[SDLK_LCTRL];
|
||||
bool cmd = keystate[SDLK_RMETA] || keystate[SDLK_LMETA];
|
||||
bool alt = keystate[SDLK_RALT] || keystate[SDLK_LALT];
|
||||
unsigned int mods;
|
||||
mods = SDL_GetModState();
|
||||
|
||||
return get_hotkey(-1, event.which, event.button, -1, -1, shift, ctrl, cmd, alt);
|
||||
}
|
||||
mods &= ~KMOD_NUM;
|
||||
mods &= ~KMOD_CAPS;
|
||||
mods &= ~KMOD_MODE;
|
||||
|
||||
const hotkey_item& get_hotkey(const SDL_JoyHatEvent& event)
|
||||
{
|
||||
CKey keystate;
|
||||
bool shift = keystate[SDLK_RSHIFT] || keystate[SDLK_LSHIFT];
|
||||
bool ctrl = keystate[SDLK_RCTRL] || keystate[SDLK_LCTRL];
|
||||
bool cmd = keystate[SDLK_RMETA] || keystate[SDLK_LMETA];
|
||||
bool alt = keystate[SDLK_RALT] || keystate[SDLK_LALT];
|
||||
// save the matching for checking right vs left keys
|
||||
if (mods & KMOD_SHIFT)
|
||||
mods |= KMOD_SHIFT;
|
||||
|
||||
return get_hotkey(-1, event.which, -1, event.hat, event.value, shift, ctrl, cmd, alt);
|
||||
}
|
||||
if (mods & KMOD_CTRL)
|
||||
mods |= KMOD_CTRL;
|
||||
|
||||
if (mods & KMOD_ALT)
|
||||
mods |= KMOD_ALT;
|
||||
|
||||
const hotkey_item& get_hotkey(const SDL_MouseButtonEvent& event)
|
||||
{
|
||||
CKey keystate;
|
||||
bool shift = keystate[SDLK_RSHIFT] || keystate[SDLK_LSHIFT];
|
||||
bool ctrl = keystate[SDLK_RCTRL] || keystate[SDLK_LCTRL];
|
||||
bool cmd = keystate[SDLK_RMETA] || keystate[SDLK_LMETA];
|
||||
bool alt = keystate[SDLK_RALT] || keystate[SDLK_LALT];
|
||||
|
||||
return get_hotkey(event.which, -1, event.button, -1, -1, shift, ctrl, cmd, alt);
|
||||
}
|
||||
|
||||
|
||||
const hotkey_item& get_hotkey(const SDL_KeyboardEvent& event)
|
||||
{
|
||||
return get_hotkey(
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
event.keysym.scancode,
|
||||
#if SDL_VERSION_ATLEAST(2,0,0)
|
||||
if (mods & KMOD_GUI)
|
||||
mods |= KMOD_GUI;
|
||||
#else
|
||||
event.keysym.unicode,
|
||||
if (mods & KMOD_META)
|
||||
mods |= KMOD_META;
|
||||
#endif
|
||||
event.keysym.sym,
|
||||
(event.keysym.mod & KMOD_SHIFT) != 0,
|
||||
(event.keysym.mod & KMOD_CTRL) != 0,
|
||||
(event.keysym.mod & KMOD_META) != 0,
|
||||
(event.keysym.mod & KMOD_ALT) != 0
|
||||
);
|
||||
|
||||
return mods;
|
||||
}
|
||||
|
||||
const std::string hotkey_base::get_name() const
|
||||
{
|
||||
std::string ret = "";
|
||||
|
||||
if (mod_ & KMOD_CTRL)
|
||||
ret += "ctrl";
|
||||
|
||||
ret += (ret.size() != 0 && !boost::algorithm::ends_with(ret, "+")? "+" : "");
|
||||
if (mod_ & KMOD_ALT)
|
||||
ret += "alt";
|
||||
|
||||
ret += (ret.size() != 0 && !boost::algorithm::ends_with(ret, "+")? "+" : "");
|
||||
if (mod_ & KMOD_SHIFT)
|
||||
ret += "shift";
|
||||
|
||||
ret += (ret.size() != 0 && !boost::algorithm::ends_with(ret, "+")? "+" : "");
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
if (mod_ & KMOD_GUI)
|
||||
#else
|
||||
if (mod_ & KMOD_META)
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
ret += "cmd";
|
||||
#else
|
||||
ret += "win";
|
||||
#endif
|
||||
|
||||
|
||||
ret += (ret.size() != 0 && !boost::algorithm::ends_with(ret, "+")? "+" : "");
|
||||
return ret += get_name_helper();
|
||||
}
|
||||
|
||||
bool hotkey_base::bindings_equal(hotkey_ptr other)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (other == hotkey_ptr())
|
||||
return false;
|
||||
|
||||
ret = mod_ == other->mod_ && bindings_equal_helper(other);
|
||||
|
||||
if (hotkey::get_hotkey_command(get_command()).scope !=
|
||||
hotkey::get_hotkey_command(other->get_command()).scope)
|
||||
return false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool hotkey_base::matches(const SDL_Event &event) const
|
||||
{
|
||||
unsigned int mods = sdl_get_mods();
|
||||
|
||||
std::string get_names(std::string id) {
|
||||
if (!hotkey::is_scope_active(hotkey::get_hotkey_command(get_command()).scope) || !active())
|
||||
return false;
|
||||
|
||||
std::vector<std::string> names;
|
||||
BOOST_FOREACH(const hotkey::hotkey_item& item, hotkeys_) {
|
||||
if (item.get_command() == id && (!item.null()) ) {
|
||||
names.push_back(item.get_name());
|
||||
}
|
||||
if((mods != mod_))
|
||||
return false;
|
||||
|
||||
return matches_helper(event);
|
||||
}
|
||||
|
||||
void hotkey_base::save(config& item) const
|
||||
{
|
||||
item["command"] = get_command();
|
||||
|
||||
item["shift"] = !!(mod_ & KMOD_SHIFT);
|
||||
item["ctrl"] = !!(mod_ & KMOD_CTRL);
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
item["cmd"] = !!(mod_ & KMOD_GUI);
|
||||
#else
|
||||
item["cmd"] = !!(mod_ & KMOD_META);
|
||||
#endif
|
||||
item["alt"] = !!(mod_ & KMOD_ALT);
|
||||
|
||||
save_helper(item);
|
||||
}
|
||||
|
||||
|
||||
hotkey_ptr create_hotkey(const std::string &id, SDL_Event &event)
|
||||
{
|
||||
hotkey_ptr base = hotkey_ptr(new hotkey_void);
|
||||
|
||||
switch(event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
{
|
||||
hotkey_keyboard_ptr keyboard(new hotkey_keyboard());
|
||||
base = boost::dynamic_pointer_cast<hotkey_base>(keyboard);
|
||||
keyboard->set_keycode(event.key.keysym.sym);
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
hotkey_mouse_ptr mouse(new hotkey_mouse());
|
||||
base = boost::dynamic_pointer_cast<hotkey_base>(mouse);
|
||||
mouse->set_button(event.button.button);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERR_G << "Trying to bind an unknown event type:" << event.type << "\n";
|
||||
break;
|
||||
}
|
||||
|
||||
return boost::algorithm::join(names, ", ");
|
||||
base->set_command(id);
|
||||
base->unset_default();
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
const hotkey_item& get_hotkey(int mouse, int joystick, int button, int hat, int value,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
hotkey_ptr load_from_config(const config& cfg)
|
||||
{
|
||||
return ::get_hotkey(mouse, joystick, button, hat, value,
|
||||
shift, ctrl, cmd, alt);
|
||||
hotkey_ptr base = hotkey_ptr();
|
||||
|
||||
const std::string& mouse_cfg = cfg["mouse"];
|
||||
if (!mouse_cfg.empty()) {
|
||||
hotkey_mouse_ptr mouse(new hotkey_mouse());
|
||||
base = boost::dynamic_pointer_cast<hotkey_base>(mouse);
|
||||
mouse->set_button(cfg["button"].to_int());
|
||||
}
|
||||
// TODO: add joystick support back
|
||||
#if 0
|
||||
const std::string& joystick_cfg = cfg["joystick"];
|
||||
if (!joystick_cfg.empty()) {
|
||||
joystick_ = cfg["joystick"].to_int();
|
||||
}
|
||||
const std::string& hat = cfg["hat"];
|
||||
if (!hat.empty()) {
|
||||
hat_ = cfg["hat"].to_int();
|
||||
value_ = cfg["value"].to_int();
|
||||
}
|
||||
|
||||
const std::string& button = cfg["button"];
|
||||
if (!button.empty()) {
|
||||
button_ = cfg["button"].to_int();
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::string& key_cfg = cfg["key"];
|
||||
if (!key_cfg.empty()) {
|
||||
hotkey_keyboard_ptr keyboard(new hotkey_keyboard());
|
||||
base = boost::dynamic_pointer_cast<hotkey_base>(keyboard);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_Keycode keycode = SDL_GetKeyFromName(key_cfg.c_str());
|
||||
if (keycode == SDLK_UNKNOWN) {
|
||||
ERR_G << "Unknown key: " << key_cfg << "\n";
|
||||
}
|
||||
#else
|
||||
SDLKey keycode = SDL_GetKeyFromName(key_cfg.c_str());
|
||||
if (keycode == SDLK_UNKNOWN) {
|
||||
ERR_G << "Unknown key: " << key_cfg << "\n";
|
||||
}
|
||||
#endif
|
||||
keyboard->set_keycode(keycode);
|
||||
}
|
||||
|
||||
if (base == hotkey_ptr())
|
||||
return base;
|
||||
|
||||
unsigned int mods = 0;
|
||||
|
||||
if(cfg["shift"].to_bool())
|
||||
mods |= KMOD_SHIFT;
|
||||
if(cfg["ctrl"].to_bool())
|
||||
mods |= KMOD_CTRL;
|
||||
if(cfg["cmd"].to_bool())
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
mods |= KMOD_GUI;
|
||||
#else
|
||||
mods |= KMOD_META;
|
||||
#endif
|
||||
if (cfg["alt"].to_bool())
|
||||
mods |= KMOD_ALT;
|
||||
|
||||
|
||||
base->set_mods(mods);
|
||||
base->set_command(cfg["command"].str());
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
const hotkey::hotkey_item& get_hotkey(int character, int keycode,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
bool hotkey_mouse::matches_helper(const SDL_Event &event) const
|
||||
{
|
||||
return ::get_hotkey(character, keycode,
|
||||
shift, ctrl, cmd, alt);
|
||||
if (event.type != SDL_MOUSEBUTTONUP &&
|
||||
event.type != SDL_MOUSEBUTTONDOWN)
|
||||
return false;
|
||||
|
||||
if (event.button.button != button_)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string hotkey_mouse::get_name_helper() const
|
||||
{
|
||||
return "mouse " + boost::lexical_cast<std::string>(button_);
|
||||
}
|
||||
|
||||
void hotkey_mouse::save_helper(config &item) const
|
||||
{
|
||||
item["mouse"] = 0;
|
||||
if (button_ != 0) item["button"] = button_;
|
||||
}
|
||||
|
||||
const std::string hotkey_keyboard::get_name_helper() const
|
||||
{
|
||||
std::string ret = std::string(SDL_GetKeyName(keycode_));
|
||||
if (ret.size() == 1)
|
||||
boost::algorithm::to_lower(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool hotkey_keyboard::matches_helper(const SDL_Event &event) const
|
||||
{
|
||||
if (event.type != SDL_KEYDOWN &&
|
||||
event.type != SDL_KEYUP)
|
||||
return false;
|
||||
|
||||
if (event.key.keysym.sym != keycode_)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hotkey_mouse::bindings_equal_helper(hotkey_ptr other) const
|
||||
{
|
||||
hotkey_mouse_ptr other_m = boost::dynamic_pointer_cast<hotkey_mouse>(other);
|
||||
if (other_m == hotkey_mouse_ptr())
|
||||
return false;
|
||||
return button_ == other_m->button_;
|
||||
}
|
||||
|
||||
void hotkey_keyboard::save_helper(config &item) const
|
||||
{
|
||||
if (keycode_ != SDLK_UNKNOWN) item["key"] = SDL_GetKeyName(keycode_);
|
||||
}
|
||||
|
||||
bool has_hotkey_item(const std::string& command)
|
||||
{
|
||||
BOOST_FOREACH(hotkey_item& item, hotkeys_)
|
||||
BOOST_FOREACH(hotkey_ptr item, hotkeys_)
|
||||
{
|
||||
if(item.get_command() == command)
|
||||
if(item->get_command() == command)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void add_hotkey(const hotkey_item& item) {
|
||||
bool hotkey_keyboard::bindings_equal_helper(hotkey_ptr other) const
|
||||
{
|
||||
hotkey_keyboard_ptr other_k = boost::dynamic_pointer_cast<hotkey_keyboard>(other);
|
||||
if (other_k == hotkey_keyboard_ptr())
|
||||
return false;
|
||||
|
||||
return keycode_ == other_k->keycode_;
|
||||
}
|
||||
|
||||
void del_hotkey(hotkey_ptr item) {
|
||||
if (hotkeys_.size() > 0)
|
||||
hotkeys_.erase(std::remove(hotkeys_.begin(), hotkeys_.end(), item));
|
||||
}
|
||||
|
||||
void add_hotkey(const hotkey_ptr item) {
|
||||
|
||||
if (item == hotkey_ptr())
|
||||
return;
|
||||
|
||||
scope_changer scope_ch;
|
||||
set_active_scopes(hotkey::get_hotkey_command(item.get_command()).scope);
|
||||
set_active_scopes(hotkey::get_hotkey_command(item->get_command()).scope);
|
||||
|
||||
hotkey_item& old_hk = (item.get_mouse() != -1 || item.get_joystick() != -1) ?
|
||||
::get_hotkey(item.get_mouse(), item.get_joystick(), item.get_button(), item.get_hat()
|
||||
, item.get_value(), item.get_shift(), item.get_ctrl(), item.get_cmd(), item.get_alt()) :
|
||||
::get_hotkey(item.get_character(), item.get_keycode(),
|
||||
item.get_shift(), item.get_ctrl(), item.get_cmd(), item.get_alt());
|
||||
if (hotkeys_.size() > 0) {
|
||||
|
||||
if (old_hk.active()) {
|
||||
old_hk.set_command(item.get_command());
|
||||
old_hk.unset_default();
|
||||
hotkeys_.erase(std::remove_if(hotkeys_.begin(), hotkeys_.end(),
|
||||
boost::bind(&hotkey_base::bindings_equal, _1, (item))), hotkeys_.end());
|
||||
}
|
||||
else
|
||||
hotkeys_.push_back(item);
|
||||
|
||||
hotkeys_.push_back(item);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void clear_hotkeys(const std::string& command)
|
||||
{
|
||||
BOOST_FOREACH(hotkey::hotkey_item& item, hotkeys_) {
|
||||
if (item.get_command() == command) {
|
||||
item.clear(); }
|
||||
BOOST_FOREACH(hotkey::hotkey_ptr item, hotkeys_) {
|
||||
if (item->get_command() == command) {
|
||||
item->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,11 +373,25 @@ void clear_hotkeys()
|
|||
hotkeys_.clear();
|
||||
}
|
||||
|
||||
const hotkey_ptr get_hotkey(const SDL_Event &event)
|
||||
{
|
||||
BOOST_FOREACH(hotkey_ptr item, hotkeys_)
|
||||
{
|
||||
if(item->matches(event))
|
||||
return item;
|
||||
}
|
||||
return hotkey_ptr(new hotkey_void());
|
||||
}
|
||||
|
||||
void load_hotkeys(const config& cfg, bool set_as_default)
|
||||
{
|
||||
BOOST_FOREACH(const config &hk, cfg.child_range("hotkey")) {
|
||||
hotkey_item item = hotkey_item(hk, set_as_default);
|
||||
if(!item.null()){
|
||||
|
||||
hotkey_ptr item = load_from_config(hk);
|
||||
if(!set_as_default)
|
||||
item->unset_default();
|
||||
|
||||
if(!item->null()){
|
||||
add_hotkey(item);
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +412,7 @@ void reset_default_hotkeys()
|
|||
}
|
||||
}
|
||||
|
||||
const std::vector<hotkey_item>& get_hotkeys()
|
||||
const hotkey_list& get_hotkeys()
|
||||
{
|
||||
return hotkeys_;
|
||||
}
|
||||
|
@ -303,258 +421,23 @@ void save_hotkeys(config& cfg)
|
|||
{
|
||||
cfg.clear_children("hotkey");
|
||||
|
||||
for(std::vector<hotkey_item>::iterator i = hotkeys_.begin();
|
||||
i != hotkeys_.end(); ++i)
|
||||
{
|
||||
if (!i->is_default())
|
||||
i->save(cfg.add_child("hotkey"));
|
||||
BOOST_FOREACH(hotkey_ptr item, hotkeys_) {
|
||||
if (!item->is_default())
|
||||
item->save(cfg.add_child("hotkey"));
|
||||
}
|
||||
}
|
||||
|
||||
bool hotkey_item::active() const
|
||||
{
|
||||
return !(command_ == "null");
|
||||
}
|
||||
|
||||
bool hotkey_item::valid() const
|
||||
{
|
||||
return (character_ | keycode_ | joystick_ | mouse_ | button_ | hat_ | value_) != 0;
|
||||
}
|
||||
std::string get_names(std::string id) {
|
||||
|
||||
// There are two kinds of "key" values.
|
||||
// One refers to actual keys, like F1 or SPACE.
|
||||
// The other refers to characters produced, eg 'M' or ':'.
|
||||
// For the latter, specifying shift+; doesn't make sense,
|
||||
// because ; is already shifted on French keyboards, for example.
|
||||
// You really want to say ':', however that is typed.
|
||||
// However, when you say shift+SPACE,
|
||||
// you're really referring to the space bar,
|
||||
// as shift+SPACE usually just produces a SPACE character.
|
||||
void hotkey_item::load_from_config(const config& cfg)
|
||||
{
|
||||
command_ = cfg["command"].str();
|
||||
|
||||
const std::string& mouse = cfg["mouse"];
|
||||
if (!mouse.empty()) {
|
||||
mouse_ = cfg["mouse"].to_int();
|
||||
button_ = cfg["button"].to_int();
|
||||
}
|
||||
const std::string& joystick = cfg["joystick"];
|
||||
if (!joystick.empty()) {
|
||||
joystick_ = cfg["joystick"].to_int();
|
||||
}
|
||||
const std::string& hat = cfg["hat"];
|
||||
if (!hat.empty()) {
|
||||
hat_ = cfg["hat"].to_int();
|
||||
value_ = cfg["value"].to_int();
|
||||
}
|
||||
|
||||
const std::string& button = cfg["button"];
|
||||
if (!button.empty()) {
|
||||
button_ = cfg["button"].to_int();
|
||||
}
|
||||
|
||||
shift_ = cfg["shift"].to_bool();
|
||||
ctrl_ = cfg["ctrl"].to_bool();
|
||||
cmd_ = cfg["cmd"].to_bool();
|
||||
alt_ = cfg["alt"].to_bool();
|
||||
|
||||
const std::string& key = cfg["key"];
|
||||
if (key.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ucs4::string wkey = unicode_cast<ucs4::string>(key);
|
||||
|
||||
// They may really want a specific key on the keyboard:
|
||||
// we assume that any single character keyname is a character.
|
||||
if (wkey.size() > 1) {
|
||||
|
||||
keycode_ = sdl_keysym_from_name(key);
|
||||
if (keycode_ == SDLK_UNKNOWN) {
|
||||
if (tolower(key[0]) != 'f') {
|
||||
ERR_CF << "hotkey key '" << key << "' invalid" << std::endl;
|
||||
} else {
|
||||
int num = lexical_cast_default<int>(key.c_str() + 1);
|
||||
keycode_ = num + SDLK_F1 - 1;
|
||||
}
|
||||
std::vector<std::string> names;
|
||||
BOOST_FOREACH(const hotkey::hotkey_ptr item, hotkeys_) {
|
||||
if (item->get_command() == id && (!item->null()) ) {
|
||||
names.push_back(item->get_name());
|
||||
}
|
||||
} else if (key == " " || shift_
|
||||
#ifdef __APPLE__
|
||||
|| alt_
|
||||
#endif
|
||||
) {
|
||||
// Space must be treated as a key because shift-space
|
||||
// isn't a different character from space,
|
||||
// and control key makes it go weird.
|
||||
// shift=yes should never be specified on single characters
|
||||
// (eg. key=m, shift=yes would be key=M),
|
||||
// but we don't want to break old preferences files.
|
||||
keycode_ = wkey[0];
|
||||
} else {
|
||||
character_ = wkey[0];
|
||||
}
|
||||
}
|
||||
|
||||
void hotkey_item::set_command(const std::string& command) {
|
||||
command_ = command;
|
||||
}
|
||||
|
||||
std::string hotkey_item::get_name() const
|
||||
{
|
||||
std::stringstream str;
|
||||
|
||||
if (shift_) { str << "shift+"; }
|
||||
if (ctrl_) { str << "ctrl+"; }
|
||||
if (cmd_) { str << "cmd+"; }
|
||||
if (alt_) { str << "alt+"; }
|
||||
|
||||
if (mouse_ >= 0) { str << _("Mouse") << mouse_ << _("Button") << button_; }
|
||||
if (character_ != -1) { str << static_cast<char>(character_); }
|
||||
if (keycode_ != -1) { str << SDL_GetKeyName(SDLKey(keycode_)); }
|
||||
if (joystick_ >= 0) { str << _("Joystick") << joystick_ << _("Button") << button_; }
|
||||
|
||||
if (value_ >= 0) {
|
||||
std::string direction;
|
||||
switch (value_) {
|
||||
case SDL_HAT_CENTERED:
|
||||
direction = _("Centered");
|
||||
break;
|
||||
case SDL_HAT_UP:
|
||||
direction = _("Up");
|
||||
break;
|
||||
case SDL_HAT_RIGHT:
|
||||
direction = _("Right");
|
||||
break;
|
||||
case SDL_HAT_DOWN:
|
||||
direction = _("Down");
|
||||
break;
|
||||
case SDL_HAT_LEFT:
|
||||
direction = _("Left");
|
||||
break;
|
||||
case SDL_HAT_RIGHTUP:
|
||||
direction = _("RightUp");
|
||||
break;
|
||||
case SDL_HAT_RIGHTDOWN:
|
||||
direction = _("RightDown");
|
||||
break;
|
||||
case SDL_HAT_LEFTUP:
|
||||
direction = _("LeftUp");
|
||||
break;
|
||||
case SDL_HAT_LEFTDOWN:
|
||||
direction = _("LeftDown");
|
||||
break;
|
||||
default:
|
||||
direction = _("Unknown");
|
||||
break;
|
||||
}
|
||||
str << _("Joystick") << joystick_ << _("Hat") << button_ << direction;
|
||||
}
|
||||
|
||||
return str.str();
|
||||
}
|
||||
|
||||
void hotkey_item::clear()
|
||||
{
|
||||
command_ = "null";
|
||||
}
|
||||
|
||||
void hotkey_item::save(config& item) const
|
||||
{
|
||||
if (get_button() >= 0) item["button"] = get_button();
|
||||
if (get_joystick() >= 0) item["joystick"] = get_joystick();
|
||||
if (get_hat() >= 0) item["hat"] = get_hat();
|
||||
if (get_value() >= 0) item["value"] = get_value();
|
||||
if (get_keycode() >= 0) item["key"] = SDL_GetKeyName(SDLKey(get_keycode()));
|
||||
if (get_character() >= 0) item["key"] = unicode_cast<utf8::string>(static_cast<ucs4::char_t>(get_character()));
|
||||
if (get_mouse() >= 0) item["mouse"] = get_mouse();
|
||||
if (get_button() >= 0) item["button"] = get_button();
|
||||
|
||||
item["command"] = get_command();
|
||||
if (get_shift()) item["shift"] = get_shift();
|
||||
if (get_ctrl() ) item["ctrl"] = get_ctrl();
|
||||
if (get_cmd() ) item["cmd"] = get_cmd();
|
||||
if (get_alt() ) item["alt"] = get_alt();
|
||||
}
|
||||
|
||||
void hotkey_item::set_jbutton(int joystick, int button,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
{
|
||||
joystick_ = joystick;
|
||||
button_ = button;
|
||||
shift_ = shift;
|
||||
ctrl_ = ctrl;
|
||||
cmd_ = cmd;
|
||||
alt_ = alt;
|
||||
}
|
||||
|
||||
void hotkey_item::set_jhat(int joystick, int hat, int value,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
{
|
||||
joystick_ = joystick;
|
||||
hat_ = hat;
|
||||
value_ = value;
|
||||
shift_ = shift;
|
||||
ctrl_ = ctrl;
|
||||
cmd_ = cmd;
|
||||
alt_ = alt;
|
||||
}
|
||||
|
||||
void hotkey_item::set_mbutton(int mouse, int button,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
{
|
||||
mouse_ = mouse;
|
||||
button_ = button;
|
||||
shift_ = shift;
|
||||
ctrl_ = ctrl;
|
||||
cmd_ = cmd;
|
||||
alt_ = alt;
|
||||
}
|
||||
|
||||
void hotkey_item::set_key(int character, int keycode,
|
||||
bool shift, bool ctrl, bool cmd, bool alt)
|
||||
{
|
||||
LOG_G << "setting hotkey: char=" << lexical_cast<std::string>(character)
|
||||
<< " keycode=" << lexical_cast<std::string>(keycode) << " "
|
||||
<< (shift ? "shift," : "")
|
||||
<< (ctrl ? "ctrl," : "")
|
||||
<< (cmd ? "cmd," : "")
|
||||
<< (alt ? "alt," : "")
|
||||
<< "\n";
|
||||
|
||||
// Sometimes control modifies by -64, ie ^A == 1.
|
||||
if (character < 64 && ctrl) {
|
||||
if (shift) {
|
||||
character += 64; }
|
||||
else {
|
||||
character += 96; }
|
||||
LOG_G << "Mapped to character " << lexical_cast<std::string>(character) << "\n";
|
||||
}
|
||||
|
||||
// For some reason on Mac OS, if cmd and shift are down, the character doesn't get upper-cased
|
||||
if (cmd && character > 96 && character < 123 && shift) {
|
||||
character -= 32; }
|
||||
|
||||
// We handle simple cases by character, others by the actual key.
|
||||
// @ and ` are exceptions related to the space character. Without these, combinations involving Ctrl or Ctrl+Shift often resolve the character value to null (or @ and `).
|
||||
// j and m exceptions are to catch Ctrl+Return/Enter, which is interpreted as Ctrl+j and Ctrl+m characters (LF and CR respectively).
|
||||
if (isprint(character) && !isspace(character) &&
|
||||
character != '@' && character != '`' &&
|
||||
!(tolower(character) == 'j' && keycode != SDLK_j) &&
|
||||
!(tolower(character) == 'm' && keycode != SDLK_m)) {
|
||||
character_ = character;
|
||||
ctrl_ = ctrl;
|
||||
cmd_ = cmd;
|
||||
alt_ = alt;
|
||||
LOG_G << "type = BY_CHARACTER\n";
|
||||
} else {
|
||||
keycode_ = keycode;
|
||||
shift_ = shift;
|
||||
ctrl_ = ctrl;
|
||||
cmd_ = cmd;
|
||||
alt_ = alt;
|
||||
LOG_G << "type = BY_KEYCODE\n";
|
||||
}
|
||||
return boost::algorithm::join(names, ", ");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,149 +17,348 @@
|
|||
|
||||
#include "config.hpp"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace hotkey {
|
||||
|
||||
/* forward declarations */
|
||||
class hotkey_base;
|
||||
class hotkey_mouse;
|
||||
class hotkey_keyboard;
|
||||
typedef boost::shared_ptr<hotkey_base> hotkey_ptr;
|
||||
typedef boost::shared_ptr<hotkey_mouse> hotkey_mouse_ptr;
|
||||
typedef boost::shared_ptr<hotkey_keyboard> hotkey_keyboard_ptr;
|
||||
|
||||
class hotkey_item {
|
||||
typedef std::vector<hotkey::hotkey_ptr> hotkey_list;
|
||||
typedef std::vector<hotkey::hotkey_ptr>::iterator hotkey_list_iter;
|
||||
|
||||
public:
|
||||
|
||||
explicit hotkey_item(const std::string& command) :
|
||||
command_(command),
|
||||
shift_(false), ctrl_(false), cmd_(false), alt_(false),
|
||||
character_(-1), keycode_(-1),
|
||||
joystick_(-1), mouse_(-1),
|
||||
button_(-1), hat_(-1), value_(-1),
|
||||
is_default_(false)
|
||||
{}
|
||||
/**
|
||||
* This is the base class for hotkey event matching.
|
||||
*/
|
||||
class hotkey_base {
|
||||
public:
|
||||
/**
|
||||
* Initialises a new empty hotkey that will be disabled
|
||||
*/
|
||||
hotkey_base() : command_("null"), is_default_(true), mod_(0) {}
|
||||
|
||||
explicit hotkey_item(const config& cfg, bool is_default):
|
||||
command_("null"),
|
||||
shift_(false), ctrl_(false), cmd_(false), alt_(false),
|
||||
character_(-1), keycode_(-1),
|
||||
joystick_(-1), mouse_(-1),
|
||||
button_(-1), hat_(-1), value_(-1),
|
||||
is_default_(is_default)
|
||||
{
|
||||
load_from_config(cfg);
|
||||
}
|
||||
void set_command(const std::string& command) {
|
||||
command_ = command;
|
||||
}
|
||||
|
||||
void load_from_config(const config& cfg);
|
||||
/**
|
||||
* Set keyboard modifiers.
|
||||
* @param mods Bitmask of SDLMod.
|
||||
*/
|
||||
void set_mods(unsigned int mods) { mod_ = mods;};
|
||||
|
||||
void set_command(const std::string& command);
|
||||
/**
|
||||
* Returns the string name of the HOTKEY_COMMAND
|
||||
* @return The unique string for a hotkey command.
|
||||
**/
|
||||
const std::string get_command() const { return command_; }
|
||||
/**
|
||||
* Returns the translated description
|
||||
* @return internationalised description of the command.
|
||||
**/
|
||||
const std::string get_description() const;
|
||||
/**
|
||||
* This controls whether the item should appear in the hotkey preferences.
|
||||
* @return true if the item should be hidden
|
||||
**/
|
||||
virtual bool hidden() const {return false;}
|
||||
|
||||
/** get the string name of the HOTKEY_COMMAND */
|
||||
const std::string get_command() const { return command_; }
|
||||
/** The translated description */
|
||||
const std::string get_description() const;
|
||||
/** @return if the item should appear in the hotkey preferences */
|
||||
bool hidden() const;
|
||||
/**
|
||||
* This indicates whether a hotkey is from the default config or if it's
|
||||
* from the user preferences.
|
||||
* @return true if from the default configurations, false otherwise
|
||||
*/
|
||||
bool is_default() const { return is_default_; }
|
||||
|
||||
bool is_default() const { return is_default_; }
|
||||
/**
|
||||
* Used to indicate that a hotkey is overriden and should be treated as
|
||||
* a user-set hotkey.
|
||||
*/
|
||||
void unset_default() {
|
||||
is_default_ = false;
|
||||
}
|
||||
|
||||
void unset_default(bool is_not_default = true) {
|
||||
is_default_ = !is_not_default;
|
||||
}
|
||||
/**
|
||||
* Unbind this hotkey by linking it to the null-command
|
||||
*/
|
||||
void clear() {command_ = "null";}
|
||||
|
||||
/// Return "name" of hotkey. Example :"ctrl+alt+g"
|
||||
std::string get_name() const;
|
||||
/**
|
||||
* Returns whether this hotkey points to the null-command
|
||||
* @return true if it points to the null-command, false otherwise.
|
||||
*/
|
||||
bool null() const { return command_ == "null"; }
|
||||
|
||||
void clear();
|
||||
/*
|
||||
* Returns whether there is a associated hotkey_command.
|
||||
* If the none of the hotkey_commands fits this hotkey_item then
|
||||
* @param get_hotkey_command will return the hotkey_command::null_command().
|
||||
* @return true if the hotkey is not bound to the null-command.
|
||||
*/
|
||||
bool active() const { return command_ != "null";}
|
||||
|
||||
bool null() const { return command_ == "null"; }
|
||||
/**
|
||||
* Evaluates whether the hotkey bindings are valid.
|
||||
* @return true if they are valid, false otherwise.
|
||||
*/
|
||||
virtual bool valid() const = 0;
|
||||
|
||||
/// returns weather there is a associated hotkey_command.
|
||||
// if the none of the hotkey_commands fits this hotkey_item then get_hotkey_command will return the hotkey_command::null_command().
|
||||
bool active() const;
|
||||
/**
|
||||
* Save the hotkey into the configuration object.
|
||||
* @param cfg The configuration object to save into.
|
||||
*/
|
||||
void save(config& cfg) const;
|
||||
|
||||
/// checks weather that hotkey "makes sense" meaning weather one of character, keycode, joystick, mouse, button, hat, value is set.
|
||||
/// i don't know what the axis_.. values are so i ignore them.
|
||||
bool valid() const;
|
||||
/**
|
||||
* Return "name" of hotkey. Example :"ctrl+alt+g"
|
||||
* @return The string representation of the keybindings
|
||||
*/
|
||||
const std::string get_name() const;
|
||||
|
||||
void save(config& cfg) const;
|
||||
/**
|
||||
* Used to evaluate whether:
|
||||
* 1. The hotkey is valid in the current scope.
|
||||
* 2. The Keyboard modifiers and SDL_Event mathes this hotkey.
|
||||
*
|
||||
* @param event The @SDL_Event that has triggered and is being evaluated.
|
||||
*/
|
||||
bool matches(const SDL_Event &event) const;
|
||||
|
||||
/// Return the actual key code.
|
||||
int get_keycode() const { return keycode_; }
|
||||
/// Returns unicode value of the pressed key.
|
||||
int get_character() const { return character_; }
|
||||
/**
|
||||
* Checks whether the hotkey bindings and scope are equal.
|
||||
* @param other the hokey bindings to compare against.
|
||||
* @return true if %other has same scope and bindings.
|
||||
*/
|
||||
virtual bool bindings_equal(hotkey_ptr other);
|
||||
|
||||
/** for buttons on devices */
|
||||
int get_button() const { return button_; }
|
||||
int get_joystick() const { return joystick_; }
|
||||
int get_hat() const { return hat_; }
|
||||
int get_mouse() const { return mouse_; }
|
||||
int get_value() const { return value_; }
|
||||
virtual ~hotkey_base() {}
|
||||
|
||||
/** modifiers */
|
||||
bool get_shift() const { return shift_; }
|
||||
bool get_ctrl() const { return ctrl_; }
|
||||
bool get_cmd() const { return cmd_; }
|
||||
bool get_alt() const { return alt_; }
|
||||
protected:
|
||||
/**
|
||||
* This is invoked by hotkey_base::get_name and must be implemented by subclasses.
|
||||
* Keyboard modifiers are handled in this class, other hotkeys in the respective classes
|
||||
*/
|
||||
virtual const std::string get_name_helper() const = 0;
|
||||
/**
|
||||
* This is invoked by hotkey_base::matches as a helper for the concrete classes.
|
||||
* Implementing classes should only check their parts of the hotkey.
|
||||
* @param event The SDL_Event being generated.
|
||||
* @returns true if they match, false otherwise.
|
||||
*/
|
||||
virtual bool matches_helper(const SDL_Event &event) const = 0;
|
||||
virtual void save_helper(config& cfg) const = 0;
|
||||
/**
|
||||
* This is invoked by hotkey_base::bindings_equal as a helper for the concrete classes.
|
||||
* Implementing classes should only check their parts of the hotkey.
|
||||
* @param other The other hotkey the check against. Not guaranteed to be the same subclass.
|
||||
* @returns true if they match, false otherwise.
|
||||
*/
|
||||
virtual bool bindings_equal_helper(hotkey_ptr other) const = 0;
|
||||
|
||||
void set_jbutton(int button, int joystick, bool shift, bool ctrl, bool cmd, bool alt);
|
||||
void set_jhat(int joystick, int hat, int value, bool shift, bool ctrl, bool cmd, bool alt);
|
||||
void set_key(int character, int keycode, bool shift, bool ctrl, bool cmd, bool alt);
|
||||
void set_mbutton(int device, int button, bool shift, bool ctrl, bool cmd, bool alt);
|
||||
|
||||
protected:
|
||||
|
||||
// The unique command associated with this item.
|
||||
// Used to bind to a hotkey_command struct.
|
||||
std::string command_;
|
||||
|
||||
// modifier keys
|
||||
bool shift_, ctrl_, cmd_, alt_;
|
||||
|
||||
// Actual unicode character
|
||||
int character_;
|
||||
|
||||
// These used for function keys (which don't have a unicode value) or
|
||||
// space (which doesn't have a distinct unicode value when shifted).
|
||||
int keycode_;
|
||||
|
||||
int joystick_, mouse_;
|
||||
int button_;
|
||||
int hat_, value_;
|
||||
|
||||
bool is_default_;
|
||||
/**
|
||||
* The command that should be executed, or "null".
|
||||
*/
|
||||
std::string command_;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
bool is_default_;
|
||||
/*
|
||||
* Keyboard modifiers. Treat as opaque, only do comparisons.
|
||||
*
|
||||
*/
|
||||
unsigned int mod_;
|
||||
};
|
||||
|
||||
/// Initiated weather there is at least one hotkey_item with the given command
|
||||
/**
|
||||
* This class is responsible for handling keys, not modifiers.
|
||||
*/
|
||||
class hotkey_keyboard: public hotkey_base {
|
||||
public:
|
||||
/**
|
||||
* Initialise new instance of this class that has no key associated with is.
|
||||
*/
|
||||
hotkey_keyboard() : hotkey_base(), keycode_(SDLK_UNKNOWN) {}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
/**
|
||||
* Set the keycode associated with this class.
|
||||
* @param keycode The SDL_Keycode that this hotkey should be associated with
|
||||
*/
|
||||
void set_keycode(SDL_Keycode keycode) {keycode_ = keycode;}
|
||||
#else
|
||||
/**
|
||||
* Set the keycode associated with this class.
|
||||
* @param keycode The SDLKey that this hotkey should be associated with
|
||||
*/
|
||||
void set_keycode(SDLKey keycode) {keycode_ = keycode;}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Checks whether this hotkey has been set to a sensible value.
|
||||
* @ return true if it is a known key
|
||||
*/
|
||||
virtual bool valid() const {return keycode_ != SDLK_UNKNOWN;}
|
||||
|
||||
protected:
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_Keycode keycode_;
|
||||
#else
|
||||
SDLKey keycode_;
|
||||
#endif
|
||||
|
||||
virtual void save_helper(config& cfg) const;
|
||||
virtual const std::string get_name_helper() const;
|
||||
virtual bool matches_helper(const SDL_Event &event) const;
|
||||
virtual bool bindings_equal_helper (hotkey_ptr other) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This class is used to return non-valid results in order to save
|
||||
* other people from null checks.
|
||||
*/
|
||||
class hotkey_void: public hotkey_base {
|
||||
public:
|
||||
hotkey_void() : hotkey_base() {}
|
||||
virtual bool valid() const {return false;}
|
||||
protected:
|
||||
virtual void save_helper(config& cfg) const {UNUSED(cfg);};
|
||||
virtual const std::string get_name_helper() const { return ""; }
|
||||
virtual bool matches_helper(const SDL_Event &event) const {UNUSED(event); return false; }
|
||||
virtual bool bindings_equal_helper(hotkey_ptr other) const { UNUSED(other); return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is responsible for handling mouse button presses.
|
||||
*/
|
||||
class hotkey_mouse: public hotkey_base {
|
||||
public:
|
||||
/**
|
||||
* Initialise new instance of this class that has no button associated with is.
|
||||
*/
|
||||
hotkey_mouse() : hotkey_base(), button_ (0) {}
|
||||
|
||||
/**
|
||||
* Returns true if the hotkey has a valid mouse button associated with it.
|
||||
* @return true if a mouse button is set, false otherwise.
|
||||
*/
|
||||
virtual bool valid() const {return button_ != 0;}
|
||||
|
||||
/* new functionality for this class */
|
||||
void set_button(int button) {button_ = button;}
|
||||
protected:
|
||||
int button_;
|
||||
|
||||
virtual void save_helper(config& cfg) const;
|
||||
virtual const std::string get_name_helper() const;
|
||||
virtual bool matches_helper(const SDL_Event &event) const;
|
||||
virtual bool bindings_equal_helper (hotkey_ptr other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* @todo not implemented
|
||||
*/
|
||||
class hotkey_joystic: public hotkey_base {
|
||||
protected:
|
||||
int button;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create and instantiate a hotkey from a config element.
|
||||
* @param cfg The config element to read for data.
|
||||
* @return The new instance of the hotkey item.
|
||||
*/
|
||||
hotkey_ptr load_from_config(const config& cfg);
|
||||
|
||||
/*
|
||||
* Scans the list of hotkeys to see if one has been bound to the command.
|
||||
* @param command The command that is searched for
|
||||
* @return true if there is a hotkey item that has the command bound.
|
||||
*/
|
||||
bool has_hotkey_item(const std::string& command);
|
||||
|
||||
void add_hotkey(const hotkey_item& item);
|
||||
/**
|
||||
* Add a hotkey to the list of hotkeys.
|
||||
* @param item The item to add.
|
||||
*/
|
||||
void add_hotkey(const hotkey_ptr item);
|
||||
|
||||
const hotkey_item& get_hotkey(int mouse, int joystick,
|
||||
int button, int hat, int value,
|
||||
bool shift, bool ctrl, bool cmd, bool alt);
|
||||
const hotkey_item& get_hotkey(int character, int keycode,
|
||||
bool shift, bool ctrl, bool cmd, bool alt);
|
||||
/**
|
||||
* Remove a hotkey from the list of hotkeys
|
||||
* @todo unusued?
|
||||
*/
|
||||
void del_hotkey(const hotkey_ptr item);
|
||||
|
||||
const hotkey_item& get_hotkey(const SDL_JoyButtonEvent& event);
|
||||
const hotkey_item& get_hotkey(const SDL_JoyHatEvent& event);
|
||||
const hotkey_item& get_hotkey(const SDL_KeyboardEvent& event);
|
||||
const hotkey_item& get_hotkey(const SDL_MouseButtonEvent& event);
|
||||
/**
|
||||
* Create a new hotkey item for a command from an SDL_Event.
|
||||
* @param id The command to bind to.
|
||||
* @param event The SDL_Event to base the creation on.
|
||||
*/
|
||||
hotkey_ptr create_hotkey(const std::string &id, SDL_Event &event);
|
||||
|
||||
/**
|
||||
* Iterate through the list of hotkeys and return a hotkey that matches
|
||||
* the SDL_Event and the current keyboard modifier state.
|
||||
* @param event The SDL_Event to use as a template.
|
||||
* @return The newly created hotkey item.
|
||||
*/
|
||||
const hotkey_ptr get_hotkey(const SDL_Event &event);
|
||||
|
||||
/**
|
||||
* Iterates through all hotkeys present in the config struct and creates and adds
|
||||
* them to the hotkey list.
|
||||
* @param cfg The config struct to load from.
|
||||
* @param set_as_default Indicates whether the config struct should be treated as the
|
||||
* default game settings.
|
||||
*/
|
||||
void load_hotkeys(const config& cfg, bool set_as_default = false);
|
||||
|
||||
/**
|
||||
* Reset all hotkeys to the defaults.
|
||||
*/
|
||||
void reset_default_hotkeys();
|
||||
|
||||
const std::vector<hotkey_item>& get_hotkeys();
|
||||
/**
|
||||
* Returns the list of hotkeys.
|
||||
*/
|
||||
const hotkey_list& get_hotkeys();
|
||||
|
||||
/**
|
||||
* Unset the command bindings for all hotkeys matching the command.
|
||||
* @command The binding to be unset
|
||||
*/
|
||||
void clear_hotkeys(const std::string& command);
|
||||
|
||||
/**
|
||||
* Unset the bindings for all hotkeys.
|
||||
*/
|
||||
void clear_hotkeys();
|
||||
|
||||
/// returns all hotkey_item s that point to this, command in the form "A,Strg+M,F4"
|
||||
/// used in the preferences menu
|
||||
|
||||
/**
|
||||
* Returns a comma-separated string of hotkey names. A hotkey name is in the form of
|
||||
* "ctrl+l" or "n" or "mouse 1". The comman separated string is of the form "ctrl+l,n,mouse 1".
|
||||
* @return The comma separated string of hotkey names.
|
||||
*/
|
||||
std::string get_names(std::string id);
|
||||
|
||||
/**
|
||||
* Save the non-default hotkeys to the config.
|
||||
* @param cfg The config to save to.
|
||||
*/
|
||||
void save_hotkeys(config& cfg);
|
||||
|
||||
/// Append a single hotkey item to @a cfg.
|
||||
//void save_hotkey(config& cfg, const hotkey_item & item);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -590,8 +590,7 @@ void hotkey_preferences_dialog::show_binding_dialog(
|
|||
disp_.update_display();
|
||||
SDL_Event event;
|
||||
event.type = 0;
|
||||
int character = -1, keycode = -1, mod = -1;
|
||||
int mouse = -1, joystick = -1, button = -1, hat = -1, value = -1;
|
||||
int keycode = -1, mod = -1;
|
||||
const int any_mod = KMOD_CTRL | KMOD_META | KMOD_ALT;
|
||||
|
||||
while ( event.type != SDL_KEYDOWN && event.type != SDL_JOYBUTTONDOWN
|
||||
|
@ -605,28 +604,11 @@ void hotkey_preferences_dialog::show_binding_dialog(
|
|||
|
||||
case SDL_KEYDOWN:
|
||||
keycode = event.key.keysym.sym;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
character = event.key.keysym.scancode,
|
||||
#else
|
||||
character = event.key.keysym.unicode;
|
||||
#endif
|
||||
mod = event.key.keysym.mod;
|
||||
break;
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
joystick = event.jbutton.which;
|
||||
button = event.jbutton.button;
|
||||
break;
|
||||
case SDL_JOYHATMOTION:
|
||||
joystick = event.jhat.which;
|
||||
hat = event.jhat.hat;
|
||||
value = event.jhat.value;
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
mouse = event.button.which;
|
||||
button = event.button.button;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
SDL_PollEvent(&event);
|
||||
disp_.flip();
|
||||
disp_.delay(10);
|
||||
|
@ -637,44 +619,16 @@ void hotkey_preferences_dialog::show_binding_dialog(
|
|||
restorer.restore();
|
||||
disp_.update_display();
|
||||
|
||||
// only if not canceled.
|
||||
// only if not cancelled.
|
||||
if (!(keycode == SDLK_ESCAPE && (mod & any_mod) == 0)) {
|
||||
|
||||
hotkey::hotkey_item newhk(id);
|
||||
const hotkey::hotkey_item* oldhk = NULL;
|
||||
hotkey::hotkey_ptr newhk;
|
||||
hotkey::hotkey_ptr oldhk;
|
||||
|
||||
CKey keystate;
|
||||
bool shift = keystate[SDLK_RSHIFT] || keystate[SDLK_LSHIFT];
|
||||
bool ctrl = keystate[SDLK_RCTRL] || keystate[SDLK_LCTRL];
|
||||
bool cmd = keystate[SDLK_RMETA] || keystate[SDLK_LMETA];
|
||||
bool alt = keystate[SDLK_RALT] || keystate[SDLK_LALT];
|
||||
|
||||
switch (event.type) {
|
||||
|
||||
case SDL_JOYHATMOTION:
|
||||
oldhk = &hotkey::get_hotkey(mouse, joystick, button, hat, value,
|
||||
shift, ctrl, cmd, alt);
|
||||
newhk.set_jhat(joystick, hat, value, shift, ctrl, cmd, alt);
|
||||
break;
|
||||
case SDL_JOYBUTTONUP:
|
||||
oldhk = &hotkey::get_hotkey(-1, joystick, button, -1, -1,
|
||||
shift, ctrl, cmd, alt);
|
||||
newhk.set_jbutton(joystick, button, shift, ctrl, cmd, alt);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
oldhk = &hotkey::get_hotkey(mouse, -1, button, -1, -1,
|
||||
shift, ctrl, cmd, alt);
|
||||
newhk.set_mbutton(mouse, button, shift, ctrl, cmd, alt);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
oldhk =
|
||||
&hotkey::get_hotkey( character, keycode,
|
||||
(mod & KMOD_SHIFT) != 0, (mod & KMOD_CTRL) != 0,
|
||||
(mod & KMOD_LMETA) != 0, (mod & KMOD_ALT) != 0 );
|
||||
newhk.set_key(character, keycode, (mod & KMOD_SHIFT) != 0,
|
||||
(mod & KMOD_CTRL) != 0, (mod & KMOD_LMETA) != 0,
|
||||
(mod & KMOD_ALT) != 0);
|
||||
oldhk = hotkey::get_hotkey(event);
|
||||
newhk = hotkey::create_hotkey(id, event);
|
||||
|
||||
#if 0
|
||||
//TODO
|
||||
// if ( (hotkey::get_id(newhk.get_command()) == hotkey::HOTKEY_SCREENSHOT
|
||||
// || hotkey::get_id(newhk.get_command()) == hotkey::HOTKEY_MAP_SCREENSHOT)
|
||||
|
@ -685,6 +639,7 @@ Control, Alt or Meta modifiers to avoid problems.")); */
|
|||
// }
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (oldhk && oldhk->active()) {
|
||||
if (oldhk->get_command() != id) {
|
||||
|
@ -692,7 +647,7 @@ Control, Alt or Meta modifiers to avoid problems.")); */
|
|||
utils::string_map symbols;
|
||||
symbols["hotkey_sequence"] = oldhk->get_name();
|
||||
symbols["old_hotkey_action"] = hotkey::get_description(oldhk->get_command());
|
||||
symbols["new_hotkey_action"] = hotkey::get_description(newhk.get_command());
|
||||
symbols["new_hotkey_action"] = hotkey::get_description(newhk->get_command());
|
||||
|
||||
std::string text =
|
||||
vgettext("\"$hotkey_sequence|\" is in use by \
|
||||
|
@ -708,6 +663,7 @@ Control, Alt or Meta modifiers to avoid problems.")); */
|
|||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "adding existing hotkey" << "\n";
|
||||
hotkey::add_hotkey(newhk);
|
||||
set_hotkey_menu(true);
|
||||
}
|
||||
|
|
1007
src/sdl/keyboard.cpp
Normal file
1007
src/sdl/keyboard.cpp
Normal file
File diff suppressed because it is too large
Load diff
48
src/sdl/keyboard.hpp
Normal file
48
src/sdl/keyboard.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_KEYBOARD_HPP_INCLUDED
|
||||
#define SDL_KEYBOARD_HPP_INCLUDED
|
||||
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Get a key code from a human-readable name
|
||||
*
|
||||
* \return key code, or SDLK_UNKNOWN if the name wasn't recognized
|
||||
*
|
||||
* \sa SDL_Keycode
|
||||
*/
|
||||
extern SDLKey SDL_GetKeyFromName(const char *name);
|
||||
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SDL_KEYBOARD_HPP_INCLUDED */
|
|
@ -2735,4 +2735,3 @@ std::ostream& operator<<(std::ostream& s, const SDL_Rect& rect)
|
|||
s << rect.x << ',' << rect.y << " x " << rect.w << ',' << rect.h;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue