fix modifier-only game keys

Fix using modifier keys such as SHIFT or CONTROL by themselves as game
keys.

Modifier keys are sent as a special keycode e.g. WXK_CTRL along with the
modifier flag, however on key release the keycode is sent but the
modifier flag is not. So check for modifier keys in process_key_press()
and always set the modifier flag so that release events are recognized
correctly.

Fix support for RAW_CTRL on Mac (which is the real control, while the
Command key is mapped to CTRL.)

Also disable the debug message emitted by wX when our modifier-only key
parsing code runs.

TODO: map modifier key names on Mac to the actual keys rather than the
wX names such as RAWCTRL.
This commit is contained in:
Rafael Kitover 2016-12-14 00:26:54 -08:00
parent a60d24e91a
commit 8c309eaaf4
2 changed files with 43 additions and 21 deletions

View File

@ -1119,6 +1119,23 @@ static bool process_key_press(bool down, int key, int mod, int joy = 0)
{
static bool in_game_key = false;
// modifier-only key releases do not set the modifier flag
// so we set it here to match key release events to key press events
switch (key) {
case WXK_SHIFT:
mod |= wxMOD_SHIFT;
break;
case WXK_ALT:
mod |= wxMOD_ALT;
break;
case WXK_CONTROL:
mod |= wxMOD_CONTROL;
break;
case WXK_RAW_CONTROL:
mod |= wxMOD_RAW_CONTROL;
break;
}
// check if key is already pressed
int kpno;
@ -1155,6 +1172,7 @@ static bool process_key_press(bool down, int key, int mod, int joy = 0)
for (int k = 0; k < b.size(); k++)
if (b[k].key == key && b[k].mod == mod && b[k].joy == joy) {
if (down) {
// press button
joypress[i] |= bmask[j];
matched_game_key = true;
}
@ -1175,6 +1193,7 @@ static bool process_key_press(bool down, int key, int mod, int joy = 0)
}
if (k2 == b.size()) {
// release button
joypress[i] &= ~bmask[j];
matched_game_key = true;
}
@ -1185,7 +1204,7 @@ static bool process_key_press(bool down, int key, int mod, int joy = 0)
}
in_game_key = matched_game_key;
return in_game_key;
}

View File

@ -1,3 +1,4 @@
#include <wx/log.h>
#include "wx/keyedit.h"
IMPLEMENT_DYNAMIC_CLASS(wxKeyTextCtrl, wxTextCtrl)
@ -71,7 +72,7 @@ wxString wxKeyTextCtrl::ToString(int mod, int key)
// before passing to ToString()
bool char_override = key > 32 && key < WXK_START && !wxIsalnum(key);
// wx also ignores modifiers (and does not report meta at all)
bool mod_override = key == WXK_SHIFT || key == WXK_CONTROL || key == WXK_ALT;
bool mod_override = key == WXK_SHIFT || key == WXK_CONTROL || key == WXK_ALT || key == WXK_RAW_CONTROL;
wxAcceleratorEntry ae(mod, char_override || mod_override ? WXK_F1 : key);
// Note: wx translates unconditionally (2.8.12, 2.9.1)!
// So any strings added below must also be translated unconditionally
@ -120,7 +121,8 @@ wxString wxKeyTextCtrl::ToString(int mod, int key)
#endif
if (s.empty() || (key != wxT('-') && s[s.size() - 1] == wxT('-')))
if (s.empty() || (key != wxT('-') && s[s.size() - 1] == wxT('-'))
|| (key != wxT('+') && s[s.size() - 1] == wxT('+')))
// bad key combo; probably also generates an assertion in wx
return wxEmptyString;
@ -193,38 +195,39 @@ bool wxKeyTextCtrl::ParseString(const wxChar* s, int len, int& mod, int& key)
// unlike ToString(), this generates a debug message rather than
// an assertion error, so it's easy to ignore and expensive to avoid
// beforehand. Instead, check for them on failure
wxLogNull disable_logging;
if (!ae.FromString(a)) {
a.MakeUpper();
#define chk_str(n, k) \
#define chk_str(n, k, m) \
do { \
wxString t = n; \
if (a.size() > t.size() && a.substr(a.size() - t.size()) == t) { \
a.replace(a.size() - t.size(), t.size(), wxT("F1")); \
wxString ss(s); \
if (ae.FromString(a)) { \
mod |= ae.GetFlags(); \
mod |= ae.GetFlags() | m; \
key = k; \
return true; \
} \
a.replace(a.size() - 2, 2, n); \
} \
} while (0)
chk_str(wxT("ALT"), WXK_ALT);
chk_str(wxT("SHIFT"), WXK_SHIFT);
chk_str(wxT("CTRL"), WXK_CONTROL);
chk_str(wxT("CONTROL"), WXK_CONTROL);
chk_str(wxT("RAWCTRL"), WXK_CONTROL);
chk_str(wxT("RAW_CTRL"), WXK_RAW_CONTROL);
chk_str(wxT("RAWCONTROL"), WXK_RAW_CONTROL);
chk_str(wxT("RAW_CONTROL"), WXK_RAW_CONTROL);
chk_str(_("ALT"), WXK_ALT);
chk_str(_("SHIFT"), WXK_SHIFT);
chk_str(_("CTRL"), WXK_CONTROL);
chk_str(_("CONTROL"), WXK_CONTROL);
chk_str(_("RAWCTRL"), WXK_RAW_CONTROL);
chk_str(_("RAW_CTRL"), WXK_RAW_CONTROL);
chk_str(_("RAWCONTROL"), WXK_RAW_CONTROL);
chk_str(_("RAW_CONTROL"), WXK_RAW_CONTROL);
chk_str(wxT("ALT"), WXK_ALT, wxMOD_ALT);
chk_str(wxT("SHIFT"), WXK_SHIFT, wxMOD_SHIFT);
chk_str(wxT("RAWCTRL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(wxT("RAW_CTRL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(wxT("RAWCONTROL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(wxT("RAW_CONTROL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(_("ALT"), WXK_ALT, wxMOD_ALT);
chk_str(_("SHIFT"), WXK_SHIFT, wxMOD_SHIFT);
chk_str(_("RAWCTRL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(_("RAW_CTRL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(_("RAWCONTROL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(_("RAW_CONTROL"), WXK_RAW_CONTROL, wxMOD_RAW_CONTROL);
chk_str(wxT("CTRL"), WXK_CONTROL, wxMOD_CONTROL);
chk_str(wxT("CONTROL"), WXK_CONTROL, wxMOD_CONTROL);
chk_str(_("CTRL"), WXK_CONTROL, wxMOD_CONTROL);
chk_str(_("CONTROL"), WXK_CONTROL, wxMOD_CONTROL);
return false;
}