Improve hot-key handling for SDL 1.2 builds

This is an extension of #450 and a correction of #470. The sdl2 branch already contains a superset of the improvements made here and will eventually be merged into master, thus overriding this work. So only include these changes in the current 1.12.x release branch.

To ensure we don't have a repeat of the mistakes in #470 I tested the following combinations (mostly Windows, some in Linux):
letter (a, b, c, etc)
punctuation (;, ., etc)
function (F1, F2, F3, etc)
Shift+letter
Shift+punctuation
Shift+function
Ctrl+Return
Ctrl+Enter
Ctrl+j
Ctrl+m
Ctrl+function
Ctrl+`
Ctrl+Shift+2 (@ on US keyboards)
Ctrl+;
Ctrl+Shift+; (colon on US keyboards)
Ctrl+Tab
Ctrl+PrintScreen
Ctrl+Pause
Ctrl+Insert
Ctrl+Delete
Ctrl+Home
Ctrl+End
Ctrl+PageUp
Ctrl+PageDown
Ctrl+Alt
Ctrl+Ctrl
Ctrl+Space
Ctrl+Alt+Space
Ctrl+direction
Ctrl+Shift
Ctrl+CapsLock
Ctrl+NumLock
Ctrl+ScrollLock

Revision of notes from #470:
Instead of specifically checking for Ctrl+j and Ctrl+m, I now make this a general check: that letters should match their respective key codes. This will still cover the Ctrl+Return/Enter combination fixed in #450, but also some of the combinations noted by others testing that PR.

Ctrl+Tab was one combination noted to not work in Linux (though it did in Windows) as it was being mis-read as Ctrl+i. Ctrl+Tab will now work correctly in Linux.

Strangely, Ctrl+Scroll Lock and Ctrl+Pause (while working in Linux) were both being mis-read as Ctrl+c in Windows. This change will cover Ctrl+Scroll Lock but Ctrl+Pause will also be read as Ctrl+Scroll Lock, because of the key code SDL detects. Similarly, Ctrl+Num Lock becomes Ctrl+Pause instead. I don't think this can be resolved because the key code is simply being read incorrectly (this includes SDL 1.2 and SDL 2.0 in Windows).

Unfortunately, I cannot test whether there will be any improvement or regression in OS X.

With hot-key handling being rewritten for SDL2 this change may seem moot, but it will still improve things for the current 1.12 release. This change also resolves concerns some have had regarding the special-case nature of the Ctrl+j/Ctrl+m check previously used.
This commit is contained in:
Wedge009 2015-10-19 13:17:17 +11:00 committed by Ignacio R. Morelle
parent ec1cb54aa3
commit 0b5ed477c3

View file

@ -98,11 +98,9 @@ hotkey::hotkey_item& get_hotkey(int character, int keycode,
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 is a letter, make sure it can match its key code. Otherwise combinations like Ctrl+Return/Enter can be mistaken for Ctrl+j or Ctrl+m (CR and LF respectively).
// Character may not match key code in case of punctuation, eg key code for semi-colon is different from key code for colon yet on US keyboards they are represented by the same key.
if (itor->get_character() != -1 && (isalpha(character) && keycode != -1 ? tolower(character) == keycode : true)) {
if (character == itor->get_character()) {
if (ctrl == itor->get_ctrl()
&& cmd == itor->get_cmd()
@ -535,11 +533,9 @@ void hotkey_item::set_key(int character, int keycode,
// 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)) {
// If character is read as a letter, only treat it as a letter if its key code matches that character. This covers cases such as Ctrl+Return/Enter, which would otherwise be mis-read as Ctrl+j or Ctrl+m (CR and LF respectively).
if (character != '@' && character != '`' &&
( (isalpha(character) && tolower(character) == keycode) || (!isalpha(character) && isprint(character) && !isspace(character)) )) {
character_ = character;
ctrl_ = ctrl;
cmd_ = cmd;