From 8c309eaaf43346743a84cd9d3c83fdef97aba24a Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Wed, 14 Dec 2016 00:26:54 -0800 Subject: [PATCH] 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. --- src/wx/panel.cpp | 21 ++++++++++++++++++- src/wx/widgets/keyedit.cpp | 43 ++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index 180bc052..a2739397 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -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; } diff --git a/src/wx/widgets/keyedit.cpp b/src/wx/widgets/keyedit.cpp index fa11f100..75e093da 100644 --- a/src/wx/widgets/keyedit.cpp +++ b/src/wx/widgets/keyedit.cpp @@ -1,3 +1,4 @@ +#include #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; }