Input refactor.
- Allow key shortcuts to run with loaded game. For example, when we set `CTRL+A` for `load most recent save state` and use `A` for some input command, holding `CTRL` and then pressing `A` will not execute the shortcut. Instead, the key press `A` will be used only as the input and nothing else. With this, we use both the input and shortcut key. - Isolate function to get keyboard key codes. As explained on [1]: "Using `GetUnicodeKey()` is in general the right thing to do if you are interested in the characters typed by the user, `GetKeyCode()` should be only used for special keys (for which `GetUnicodeKey()` returns `WXK_NONE`)." We also allow special keys to be mapped, hence the requirement of using both functions. [1] https://docs.wxwidgets.org/3.1/classwx_key_event.html - Allow use of unicode keys for input and shortcut. Use format `KeyCode:Modifier` for saving/loading unicode keys. `WxWidgets=3.{0,1}` does not create an accelerator from strings with unicode keys such as `ç` (`FromString` function). It fails with an assertion error and stops execution. At the same time, we use the keys' strings that are known for WxWidgets, such as `A`, `CTRL+O`, `PAGEUP` etc. Use both `EVT_KEY_DOWN` and `EVT_CHAR`. `EVT_CHAR` is better than `EVT_KEY_DOWN` here because it is where the raw key events will have been cooked using whatever recipes are in effect from the os, locale, international keyboard settings, etc. - Enable SDL joysticks input as key shortcuts. Start/Stop polling joysticks on Unload/load game. Our main loop already polls the joystick, we don't need the timer while a game is running. - Create function `str_split_with_sep` and use it. For when we parse strings that may include the sep string, such as game input and key shortcuts.
This commit is contained in:
parent
6b257d52f2
commit
baa0341bd5
|
@ -4953,7 +4953,6 @@ void gbEmulate(int ticksToStop)
|
|||
if (turbo_button_pressed) {
|
||||
if (!speedup_throttle_set && throttle != speedup_throttle) {
|
||||
last_throttle = throttle;
|
||||
//throttle = speedup_throttle;
|
||||
soundSetThrottle(speedup_throttle);
|
||||
speedup_throttle_set = true;
|
||||
}
|
||||
|
@ -4970,7 +4969,6 @@ void gbEmulate(int ticksToStop)
|
|||
framesToSkip = speedup_frame_skip;
|
||||
}
|
||||
else if (speedup_throttle_set) {
|
||||
//throttle = last_throttle;
|
||||
soundSetThrottle(last_throttle);
|
||||
|
||||
speedup_throttle_set = false;
|
||||
|
|
|
@ -3799,7 +3799,6 @@ void CPULoop(int ticks)
|
|||
if (turbo_button_pressed) {
|
||||
if (!speedup_throttle_set && throttle != speedup_throttle) {
|
||||
last_throttle = throttle;
|
||||
//throttle = speedup_throttle;
|
||||
soundSetThrottle(speedup_throttle);
|
||||
speedup_throttle_set = true;
|
||||
}
|
||||
|
@ -3816,7 +3815,6 @@ void CPULoop(int ticks)
|
|||
framesToSkip = speedup_frame_skip;
|
||||
}
|
||||
else if (speedup_throttle_set) {
|
||||
//throttle = last_throttle;
|
||||
soundSetThrottle(last_throttle);
|
||||
|
||||
speedup_throttle_set = false;
|
||||
|
|
|
@ -739,6 +739,7 @@ set(
|
|||
viewsupt.cpp
|
||||
wayland.cpp
|
||||
strutils.cpp
|
||||
wxutil.cpp
|
||||
widgets/keyedit.cpp
|
||||
widgets/joyedit.cpp
|
||||
widgets/sdljoy.cpp
|
||||
|
@ -769,6 +770,7 @@ set(
|
|||
viewsupt.h
|
||||
wxhead.h
|
||||
wayland.h
|
||||
wxutil.h
|
||||
widgets/wx/keyedit.h
|
||||
widgets/wx/joyedit.h
|
||||
widgets/wx/sdljoy.h
|
||||
|
|
|
@ -2706,7 +2706,6 @@ EVT_HANDLER(EmulatorDirectories, "Directories...")
|
|||
EVT_HANDLER(JoypadConfigure, "Joypad options...")
|
||||
{
|
||||
wxDialog* dlg = GetXRCDialog("JoypadConfig");
|
||||
joy.Attach(NULL);
|
||||
joy.Add();
|
||||
|
||||
if (ShowModal(dlg) == wxID_OK)
|
||||
|
@ -2718,9 +2717,12 @@ EVT_HANDLER(JoypadConfigure, "Joypad options...")
|
|||
EVT_HANDLER(Customize, "Customize UI...")
|
||||
{
|
||||
wxDialog* dlg = GetXRCDialog("AccelConfig");
|
||||
joy.Add();
|
||||
|
||||
if (ShowModal(dlg) == wxID_OK)
|
||||
update_opts();
|
||||
|
||||
SetJoystick();
|
||||
}
|
||||
|
||||
#ifndef NO_ONLINEUPDATES
|
||||
|
@ -3068,6 +3070,9 @@ void SetLinkTypeMenu(const char* type, int value)
|
|||
mf->SetMenuOption(type, 1);
|
||||
gopts.gba_link_type = value;
|
||||
update_opts();
|
||||
#ifndef NO_LINK
|
||||
CloseLink();
|
||||
#endif
|
||||
mf->EnableNetworkMenu();
|
||||
}
|
||||
|
||||
|
@ -3097,33 +3102,21 @@ EVT_HANDLER_MASK(LanLink, "Start Network link", CMDEN_LINK_ANY)
|
|||
|
||||
EVT_HANDLER(LinkType0Nothing, "Link nothing")
|
||||
{
|
||||
#ifndef NO_LINK
|
||||
CloseLink();
|
||||
#endif
|
||||
SetLinkTypeMenu("LinkType0Nothing", 0);
|
||||
}
|
||||
|
||||
EVT_HANDLER(LinkType1Cable, "Link cable")
|
||||
{
|
||||
#ifndef NO_LINK
|
||||
CloseLink();
|
||||
#endif
|
||||
SetLinkTypeMenu("LinkType1Cable", 1);
|
||||
}
|
||||
|
||||
EVT_HANDLER(LinkType2Wireless, "Link wireless")
|
||||
{
|
||||
#ifndef NO_LINK
|
||||
CloseLink();
|
||||
#endif
|
||||
SetLinkTypeMenu("LinkType2Wireless", 2);
|
||||
}
|
||||
|
||||
EVT_HANDLER(LinkType3GameCube, "Link GameCube")
|
||||
{
|
||||
#ifndef NO_LINK
|
||||
CloseLink();
|
||||
#endif
|
||||
SetLinkTypeMenu("LinkType3GameCube", 3);
|
||||
}
|
||||
|
||||
|
|
|
@ -1695,19 +1695,6 @@ public:
|
|||
}
|
||||
} JoyPadConfigHandler[4];
|
||||
|
||||
class JoystickPoller : public wxTimer {
|
||||
public:
|
||||
void Notify() {
|
||||
wxGetApp().frame->PollJoysticks();
|
||||
}
|
||||
void ShowDialog(wxShowEvent& ev) {
|
||||
if (ev.IsShown())
|
||||
Start(50);
|
||||
else
|
||||
Stop();
|
||||
}
|
||||
};
|
||||
|
||||
// manage fullscreen mode widget
|
||||
// technically, it's more than a validator: it modifies the widget as well
|
||||
class ScreenModeList : public wxValidator {
|
||||
|
@ -2003,7 +1990,7 @@ static bool treeid_to_name(int id, wxString& name, wxTreeCtrl* tc,
|
|||
}
|
||||
|
||||
// for sorting accels by command ID
|
||||
static bool cmdid_lt(const wxAcceleratorEntry& a, const wxAcceleratorEntry& b)
|
||||
static bool cmdid_lt(const wxAcceleratorEntryUnicode& a, const wxAcceleratorEntryUnicode& b)
|
||||
{
|
||||
return a.GetCommand() < b.GetCommand();
|
||||
}
|
||||
|
@ -2015,7 +2002,7 @@ public:
|
|||
wxControlWithItems* lb;
|
||||
wxAcceleratorEntry_v user_accels, accels;
|
||||
wxWindow *asb, *remb;
|
||||
wxKeyTextCtrl* key;
|
||||
wxJoyKeyTextCtrl* key;
|
||||
wxControl* curas;
|
||||
|
||||
// since this is not the actual dialog, derived from wxDialog, which is
|
||||
|
@ -2076,10 +2063,17 @@ public:
|
|||
asb->Enable(!key->GetValue().empty());
|
||||
int cmd = id->val;
|
||||
|
||||
for (size_t i = 0; i < accels.size(); i++)
|
||||
if (accels[i].GetCommand() == cmdtab[cmd].cmd_id)
|
||||
lb->Append(wxKeyTextCtrl::ToString(accels[i].GetFlags(),
|
||||
accels[i].GetKeyCode()));
|
||||
for (size_t i = 0; i < accels.size(); ++i) {
|
||||
if (accels[i].GetCommand() == cmdtab[cmd].cmd_id) {
|
||||
if (accels[i].GetJoystick() == 0) {
|
||||
wxString key = wxJoyKeyTextCtrl::ToCandidateString(accels[i].GetFlags(), accels[i].GetKeyCode());
|
||||
lb->Append(key);
|
||||
}
|
||||
else {
|
||||
lb->Append(accels[i].GetUkey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// after selecting a key in key list, enable Remove button
|
||||
|
@ -2099,10 +2093,11 @@ public:
|
|||
return;
|
||||
|
||||
wxString selstr = lb->GetString(lsel);
|
||||
int selmod, selkey;
|
||||
int selmod, selkey, seljoy;
|
||||
|
||||
if (!wxKeyTextCtrl::FromString(selstr, selmod, selkey))
|
||||
return; // this should never happen
|
||||
if (!wxJoyKeyTextCtrl::FromString(selstr, selmod, selkey, seljoy))
|
||||
// this should never happen
|
||||
return;
|
||||
|
||||
remb->Enable(false);
|
||||
|
||||
|
@ -2115,7 +2110,9 @@ public:
|
|||
// first drop from user accels, if applicable
|
||||
for (wxAcceleratorEntry_v::iterator i = user_accels.begin();
|
||||
i < user_accels.end(); ++i)
|
||||
if (i->GetFlags() == selmod && i->GetKeyCode() == selkey) {
|
||||
if ((i->GetFlags() == selmod && i->GetKeyCode() == selkey)
|
||||
|| (seljoy != 0 && i->GetUkey() == selstr))
|
||||
{
|
||||
user_accels.erase(i);
|
||||
break;
|
||||
}
|
||||
|
@ -2124,15 +2121,19 @@ public:
|
|||
wxAcceleratorEntry_v& sys_accels = wxGetApp().frame->sys_accels;
|
||||
|
||||
for (size_t i = 0; i < sys_accels.size(); i++)
|
||||
if (sys_accels[i].GetFlags() == selmod && sys_accels[i].GetKeyCode() == selkey) {
|
||||
wxAcceleratorEntry ne(selmod, selkey, XRCID("NOOP"));
|
||||
if ((sys_accels[i].GetFlags() == selmod && sys_accels[i].GetKeyCode() == selkey)
|
||||
|| (seljoy != 0 && sys_accels[i].GetUkey() == selstr)) // joystick system bindings?
|
||||
{
|
||||
wxAcceleratorEntryUnicode ne(sys_accels[i].GetUkey(), sys_accels[i].GetJoystick(), selmod, selkey, XRCID("NOOP"));
|
||||
user_accels.push_back(ne);
|
||||
}
|
||||
|
||||
// finally, remove from accels instead of recomputing
|
||||
for (wxAcceleratorEntry_v::iterator i = accels.begin();
|
||||
i < accels.end(); ++i)
|
||||
if (i->GetFlags() == selmod && i->GetKeyCode() == selkey) {
|
||||
if ((i->GetFlags() == selmod && i->GetKeyCode() == selkey)
|
||||
|| (seljoy != 0 && i->GetUkey() == selstr))
|
||||
{
|
||||
accels.erase(i);
|
||||
break;
|
||||
}
|
||||
|
@ -2164,10 +2165,11 @@ public:
|
|||
if (!csel.IsOk() || accel.empty())
|
||||
return;
|
||||
|
||||
int acmod, ackey;
|
||||
int acmod, ackey, acjoy;
|
||||
|
||||
if (!wxKeyTextCtrl::FromString(accel, acmod, ackey))
|
||||
return; // this should never happen
|
||||
if (!wxJoyKeyTextCtrl::FromString(accel, acmod, ackey, acjoy))
|
||||
// this should never happen
|
||||
return;
|
||||
|
||||
for (unsigned int i = 0; i < lb->GetCount(); i++)
|
||||
if (lb->GetString(i) == accel)
|
||||
|
@ -2178,15 +2180,17 @@ public:
|
|||
// first drop from user accels, if applicable
|
||||
for (wxAcceleratorEntry_v::iterator i = user_accels.begin();
|
||||
i < user_accels.end(); ++i)
|
||||
if (i->GetFlags() == acmod && i->GetKeyCode() == ackey) {
|
||||
if ((i->GetFlags() == acmod && i->GetKeyCode() == ackey && i->GetJoystick() != acjoy)
|
||||
|| (acjoy != 0 && i->GetUkey() == accel)) {
|
||||
user_accels.erase(i);
|
||||
break;
|
||||
}
|
||||
|
||||
// then assign to this command
|
||||
const TreeInt* id = static_cast<const TreeInt*>(tc->GetItemData(csel));
|
||||
wxAcceleratorEntry ne(acmod, ackey, cmdtab[id->val].cmd_id);
|
||||
wxAcceleratorEntryUnicode ne(accel, acjoy, acmod, ackey, cmdtab[id->val].cmd_id);
|
||||
user_accels.push_back(ne);
|
||||
|
||||
// now assigned to this cmd...
|
||||
wxString lab;
|
||||
treeid_to_name(id->val, lab, tc, tc->GetRootItem());
|
||||
|
@ -2207,9 +2211,9 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
int acmod, ackey;
|
||||
int acmod, ackey, acjoy;
|
||||
|
||||
if (!wxKeyTextCtrl::FromString(nkey, acmod, ackey)) {
|
||||
if (!wxJoyKeyTextCtrl::FromString(nkey, acmod, ackey, acjoy)) {
|
||||
// this should never happen
|
||||
key->SetValue(wxT(""));
|
||||
asb->Enable(false);
|
||||
|
@ -2220,7 +2224,8 @@ public:
|
|||
int cmd = -1;
|
||||
|
||||
for (size_t i = 0; i < accels.size(); i++)
|
||||
if (accels[i].GetFlags() == acmod && accels[i].GetKeyCode() == ackey) {
|
||||
if ((accels[i].GetFlags() == acmod && accels[i].GetKeyCode() == ackey)
|
||||
|| (acjoy != 0 && accels[i].GetUkey() == nkey)) {
|
||||
int cmdid = accels[i].GetCommand();
|
||||
|
||||
for (cmd = 0; cmd < ncmds; cmd++)
|
||||
|
@ -2358,7 +2363,7 @@ public:
|
|||
} throttle_ctrl;
|
||||
|
||||
static class SpeedupThrottleCtrl_t : public wxEvtHandler {
|
||||
public:
|
||||
public:
|
||||
wxSpinCtrl* speedup_throttle_spin;
|
||||
wxCheckBox* frame_skip_cb;
|
||||
|
||||
|
@ -2418,7 +2423,7 @@ public:
|
|||
|
||||
speedup_throttle_frame_skip = prev_frame_skip_cb = checked;
|
||||
}
|
||||
|
||||
|
||||
void Init(wxShowEvent& ev)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
|
@ -2547,10 +2552,11 @@ wxAcceleratorEntry_v MainFrame::get_accels(wxAcceleratorEntry_v user_accels)
|
|||
// silently keep only last defined binding
|
||||
// same horribly inefficent O(n*m) search for duplicates as above..
|
||||
for (size_t i = 0; i < user_accels.size(); i++) {
|
||||
const wxAcceleratorEntry& ae = user_accels[i];
|
||||
const wxAcceleratorEntryUnicode& ae = user_accels[i];
|
||||
|
||||
for (wxAcceleratorEntry_v::iterator e = accels.begin(); e < accels.end(); ++e)
|
||||
if (ae.GetFlags() == e->GetFlags() && ae.GetKeyCode() == e->GetKeyCode()) {
|
||||
if ((ae.GetFlags() == e->GetFlags() && ae.GetKeyCode() == e->GetKeyCode())
|
||||
|| (ae.GetJoystick() == e->GetJoystick() && ae.GetUkey() == e->GetUkey())) {
|
||||
accels.erase(e);
|
||||
break;
|
||||
}
|
||||
|
@ -2572,9 +2578,12 @@ void MainFrame::set_global_accels()
|
|||
// the menus will be added now
|
||||
|
||||
// first, zero out menu item on all accels
|
||||
for (size_t i = 0; i < accels.size(); i++)
|
||||
accels[i].Set(accels[i].GetFlags(), accels[i].GetKeyCode(),
|
||||
accels[i].GetCommand());
|
||||
for (size_t i = 0; i < accels.size(); ++i) {
|
||||
accels[i].Set(accels[i].GetUkey(), accels[i].GetJoystick(), accels[i].GetFlags(), accels[i].GetKeyCode(), accels[i].GetCommand());
|
||||
if (accels[i].GetJoystick()) {
|
||||
joy.Add(accels[i].GetJoystick() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// yet another O(n*m) loop. I really ought to sort the accel arrays
|
||||
for (int i = 0; i < ncmds; i++) {
|
||||
|
@ -2583,25 +2592,24 @@ void MainFrame::set_global_accels()
|
|||
if (!mi)
|
||||
continue;
|
||||
|
||||
// only *last* accelerator is made visible in menu
|
||||
// only *last* accelerator is made visible in menu (non-unicode)
|
||||
// and is flagged as such by setting menu item in accel
|
||||
// the last is chosen so menu overrides non-menu and user overrides
|
||||
// system
|
||||
int cmd = cmdtab[i].cmd_id;
|
||||
int last_accel = -1;
|
||||
|
||||
for (size_t j = 0; j < accels.size(); j++)
|
||||
for (size_t j = 0; j < accels.size(); ++j)
|
||||
if (cmd == accels[j].GetCommand())
|
||||
last_accel = j;
|
||||
|
||||
if (last_accel >= 0) {
|
||||
DoSetAccel(mi, &accels[last_accel]);
|
||||
accels[last_accel].Set(accels[last_accel].GetFlags(),
|
||||
accels[last_accel].GetKeyCode(),
|
||||
accels[last_accel].GetCommand(), mi);
|
||||
} else
|
||||
accels[last_accel].Set(accels[last_accel].GetUkey(), accels[last_accel].GetJoystick(), accels[last_accel].GetFlags(), accels[last_accel].GetKeyCode(), accels[last_accel].GetCommand(), mi);
|
||||
} else {
|
||||
// clear out user-cleared menu items
|
||||
DoSetAccel(mi, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, install a global accelerator table for any non-menu accels
|
||||
|
@ -2612,7 +2620,7 @@ void MainFrame::set_global_accels()
|
|||
len++;
|
||||
|
||||
if (len) {
|
||||
wxAcceleratorEntry tab[1000];
|
||||
wxAcceleratorEntryUnicode tab[1000];
|
||||
|
||||
for (size_t i = 0, j = 0; i < accels.size(); i++)
|
||||
if (!accels[i].GetMenuItem())
|
||||
|
@ -2627,7 +2635,7 @@ void MainFrame::set_global_accels()
|
|||
|
||||
// save recent accels
|
||||
for (int i = 0; i < 10; i++)
|
||||
recent_accel[i] = wxAcceleratorEntry();
|
||||
recent_accel[i] = wxAcceleratorEntryUnicode();
|
||||
|
||||
for (size_t i = 0; i < accels.size(); i++)
|
||||
if (accels[i].GetCommand() >= wxID_FILE1 && accels[i].GetCommand() <= wxID_FILE10)
|
||||
|
@ -2922,7 +2930,7 @@ bool MainFrame::BindControls()
|
|||
}
|
||||
|
||||
if (a)
|
||||
sys_accels.push_back(*a);
|
||||
sys_accels.push_back(wxAcceleratorEntryUnicode(a));
|
||||
else
|
||||
// strip from label so user isn't confused
|
||||
DoSetAccel(mi, NULL);
|
||||
|
@ -3830,13 +3838,6 @@ bool MainFrame::BindControls()
|
|||
NULL, &JoyPadConfigHandler[i]);
|
||||
}
|
||||
|
||||
// poll the joystick
|
||||
JoystickPoller* jpoll = new JoystickPoller();
|
||||
|
||||
joyDialog->Connect(wxID_ANY, wxEVT_SHOW,
|
||||
wxShowEventHandler(JoystickPoller::ShowDialog),
|
||||
jpoll, jpoll);
|
||||
|
||||
joyDialog->Fit();
|
||||
}
|
||||
|
||||
|
@ -3860,7 +3861,7 @@ bool MainFrame::BindControls()
|
|||
accel_config_handler.lb = lb;
|
||||
accel_config_handler.asb = SafeXRCCTRL<wxButton>(d, "Assign");
|
||||
accel_config_handler.remb = SafeXRCCTRL<wxButton>(d, "Remove");
|
||||
accel_config_handler.key = SafeXRCCTRL<wxKeyTextCtrl>(d, "Shortcut");
|
||||
accel_config_handler.key = SafeXRCCTRL<wxJoyKeyTextCtrl>(d, "Shortcut");
|
||||
accel_config_handler.curas = SafeXRCCTRL<wxControl>(d, "AlreadyThere");
|
||||
accel_config_handler.key->MoveBeforeInTabOrder(accel_config_handler.asb);
|
||||
accel_config_handler.key->SetMultikey(0);
|
||||
|
|
147
src/wx/opts.cpp
147
src/wx/opts.cpp
|
@ -42,9 +42,9 @@
|
|||
opts_t gopts;
|
||||
|
||||
// having the standard menu accels here means they will work even without menus
|
||||
const wxAcceleratorEntry default_accels[] = {
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('C'), XRCID("CheatsList")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('N'), XRCID("NextFrame")),
|
||||
const wxAcceleratorEntryUnicode default_accels[] = {
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('C'), XRCID("CheatsList")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('N'), XRCID("NextFrame")),
|
||||
// some ports add ctrl-q anyway, so may as well make it official
|
||||
// maybe make alt-f4 universal as well...
|
||||
// FIXME: ctrl-Q does not work on wxMSW
|
||||
|
@ -56,79 +56,79 @@ const wxAcceleratorEntry default_accels[] = {
|
|||
// this was annoying people #298
|
||||
//wxAcceleratorEntry(wxMOD_CMD, wxT('X'), wxID_EXIT),
|
||||
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('Q'), wxID_EXIT),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('Q'), wxID_EXIT),
|
||||
// FIXME: ctrl-W does not work on wxMSW
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('W'), wxID_CLOSE),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('W'), wxID_CLOSE),
|
||||
// load most recent is more commonly used than load other
|
||||
//wxAcceleratorEntry(wxMOD_CMD, wxT('L'), XRCID("Load")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('L'), XRCID("LoadGameRecent")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F1, XRCID("LoadGame01")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F2, XRCID("LoadGame02")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F3, XRCID("LoadGame03")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F4, XRCID("LoadGame04")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F5, XRCID("LoadGame05")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F6, XRCID("LoadGame06")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F7, XRCID("LoadGame07")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F8, XRCID("LoadGame08")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F9, XRCID("LoadGame09")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_F10, XRCID("LoadGame10")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_PAUSE, XRCID("Pause")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('P'), XRCID("Pause")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('R'), XRCID("Reset")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('L'), XRCID("LoadGameRecent")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F1, XRCID("LoadGame01")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F2, XRCID("LoadGame02")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F3, XRCID("LoadGame03")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F4, XRCID("LoadGame04")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F5, XRCID("LoadGame05")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F6, XRCID("LoadGame06")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F7, XRCID("LoadGame07")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F8, XRCID("LoadGame08")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F9, XRCID("LoadGame09")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_F10, XRCID("LoadGame10")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_PAUSE, XRCID("Pause")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('P'), XRCID("Pause")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('R'), XRCID("Reset")),
|
||||
// add shortcuts for original size multiplier #415
|
||||
wxAcceleratorEntry(wxMOD_NONE, wxT('1'), XRCID("SetSize1x")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, wxT('2'), XRCID("SetSize2x")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, wxT('3'), XRCID("SetSize3x")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, wxT('4'), XRCID("SetSize4x")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, wxT('5'), XRCID("SetSize5x")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, wxT('6'), XRCID("SetSize6x")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, wxT('1'), XRCID("SetSize1x")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, wxT('2'), XRCID("SetSize2x")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, wxT('3'), XRCID("SetSize3x")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, wxT('4'), XRCID("SetSize4x")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, wxT('5'), XRCID("SetSize5x")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, wxT('6'), XRCID("SetSize6x")),
|
||||
// save oldest is more commonly used than save other
|
||||
//wxAcceleratorEntry(wxMOD_CMD, wxT('S'), XRCID("Save")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('S'), XRCID("SaveGameOldest")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F1, XRCID("SaveGame01")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F2, XRCID("SaveGame02")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F3, XRCID("SaveGame03")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F4, XRCID("SaveGame04")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F5, XRCID("SaveGame05")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F6, XRCID("SaveGame06")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F7, XRCID("SaveGame07")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F8, XRCID("SaveGame08")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F9, XRCID("SaveGame09")),
|
||||
wxAcceleratorEntry(wxMOD_SHIFT, WXK_F10, XRCID("SaveGame10")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('S'), XRCID("SaveGameOldest")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F1, XRCID("SaveGame01")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F2, XRCID("SaveGame02")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F3, XRCID("SaveGame03")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F4, XRCID("SaveGame04")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F5, XRCID("SaveGame05")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F6, XRCID("SaveGame06")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F7, XRCID("SaveGame07")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F8, XRCID("SaveGame08")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F9, XRCID("SaveGame09")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_SHIFT, WXK_F10, XRCID("SaveGame10")),
|
||||
// I prefer the SDL ESC key binding
|
||||
//wxAcceleratorEntry(wxMOD_NONE, WXK_ESCAPE, XRCID("ToggleFullscreen"),
|
||||
// alt-enter is more standard anyway
|
||||
wxAcceleratorEntry(wxMOD_ALT, WXK_RETURN, XRCID("ToggleFullscreen")),
|
||||
wxAcceleratorEntry(wxMOD_ALT, wxT('1'), XRCID("JoypadAutofireA")),
|
||||
wxAcceleratorEntry(wxMOD_ALT, wxT('2'), XRCID("JoypadAutofireB")),
|
||||
wxAcceleratorEntry(wxMOD_ALT, wxT('3'), XRCID("JoypadAutofireL")),
|
||||
wxAcceleratorEntry(wxMOD_ALT, wxT('4'), XRCID("JoypadAutofireR")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('1'), XRCID("VideoLayersBG0")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('2'), XRCID("VideoLayersBG1")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('3'), XRCID("VideoLayersBG2")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('4'), XRCID("VideoLayersBG3")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('5'), XRCID("VideoLayersOBJ")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('6'), XRCID("VideoLayersWIN0")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('7'), XRCID("VideoLayersWIN1")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('8'), XRCID("VideoLayersOBJWIN")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('B'), XRCID("Rewind")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_ALT, WXK_RETURN, XRCID("ToggleFullscreen")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_ALT, wxT('1'), XRCID("JoypadAutofireA")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_ALT, wxT('2'), XRCID("JoypadAutofireB")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_ALT, wxT('3'), XRCID("JoypadAutofireL")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_ALT, wxT('4'), XRCID("JoypadAutofireR")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('1'), XRCID("VideoLayersBG0")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('2'), XRCID("VideoLayersBG1")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('3'), XRCID("VideoLayersBG2")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('4'), XRCID("VideoLayersBG3")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('5'), XRCID("VideoLayersOBJ")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('6'), XRCID("VideoLayersWIN0")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('7'), XRCID("VideoLayersWIN1")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('8'), XRCID("VideoLayersOBJWIN")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('B'), XRCID("Rewind")),
|
||||
// following are not in standard menus
|
||||
// FILExx are filled in when recent menu is filled
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F1, wxID_FILE1),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F2, wxID_FILE2),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F3, wxID_FILE3),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F4, wxID_FILE4),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F5, wxID_FILE5),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F6, wxID_FILE6),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F7, wxID_FILE7),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F8, wxID_FILE8),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F9, wxID_FILE9),
|
||||
wxAcceleratorEntry(wxMOD_CMD, WXK_F10, wxID_FILE10),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('0'), XRCID("VideoLayersReset")),
|
||||
wxAcceleratorEntry(wxMOD_CMD, wxT('G'), XRCID("ChangeFilter")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_NUMPAD_ADD, XRCID("IncreaseVolume")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_NUMPAD_SUBTRACT, XRCID("DecreaseVolume")),
|
||||
wxAcceleratorEntry(wxMOD_NONE, WXK_NUMPAD_ENTER, XRCID("ToggleSound"))
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F1, wxID_FILE1),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F2, wxID_FILE2),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F3, wxID_FILE3),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F4, wxID_FILE4),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F5, wxID_FILE5),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F6, wxID_FILE6),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F7, wxID_FILE7),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F8, wxID_FILE8),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F9, wxID_FILE9),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, WXK_F10, wxID_FILE10),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('0'), XRCID("VideoLayersReset")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_CMD, wxT('G'), XRCID("ChangeFilter")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_NUMPAD_ADD, XRCID("IncreaseVolume")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_NUMPAD_SUBTRACT, XRCID("DecreaseVolume")),
|
||||
wxAcceleratorEntryUnicode(wxMOD_NONE, WXK_NUMPAD_ENTER, XRCID("ToggleSound"))
|
||||
};
|
||||
const int num_def_accels = sizeof(default_accels) / sizeof(default_accels[0]);
|
||||
|
||||
|
@ -669,17 +669,15 @@ void load_opts()
|
|||
kbopt.append(cmdtab[i].cmd);
|
||||
|
||||
if (cfg->Read(kbopt, &s) && s.size()) {
|
||||
wxAcceleratorEntry_v val = wxKeyTextCtrl::FromString(s);
|
||||
wxAcceleratorEntry_v val = wxJoyKeyTextCtrl::ToAccelFromString(s);
|
||||
|
||||
if (!val.size())
|
||||
wxLogWarning(_("Invalid key binding %s for %s"), s.c_str(), kbopt.c_str());
|
||||
else {
|
||||
for (size_t j = 0; j < val.size(); j++)
|
||||
val[j].Set(val[j].GetFlags(), val[j].GetKeyCode(),
|
||||
cmdtab[i].cmd_id);
|
||||
val[j].Set(val[j].GetUkey(), val[j].GetJoystick(), val[j].GetFlags(), val[j].GetKeyCode(), cmdtab[i].cmd_id);
|
||||
|
||||
gopts.accels.insert(gopts.accels.end(),
|
||||
val.begin(), val.end());
|
||||
gopts.accels.insert(gopts.accels.end(), val.begin(), val.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -763,7 +761,7 @@ void update_opts()
|
|||
wxString s, o;
|
||||
wxString optname;
|
||||
optname.Printf(wxT("Joypad/%d/%s"), i + 1, joynames[j].c_str());
|
||||
s = wxJoyKeyTextCtrl::ToString(gopts.joykey_bindings[i][j]);
|
||||
s = wxJoyKeyTextCtrl::ToString(gopts.joykey_bindings[i][j], wxT(','), true);
|
||||
cfg->Read(optname, &o);
|
||||
|
||||
if (o != s)
|
||||
|
@ -825,7 +823,7 @@ void update_opts()
|
|||
break;
|
||||
|
||||
wxAcceleratorEntry_v nv(i, j);
|
||||
wxString nvs = wxKeyTextCtrl::ToString(nv);
|
||||
wxString nvs = wxJoyKeyTextCtrl::FromAccelToString(nv, wxT(','), true);
|
||||
|
||||
if (nvs != cfg->Read(command))
|
||||
cfg->Write(command, nvs);
|
||||
|
@ -953,11 +951,10 @@ bool opt_set(const wxString& name, const wxString& val)
|
|||
}
|
||||
|
||||
if (!val.empty()) {
|
||||
auto aval = wxKeyTextCtrl::FromString(val);
|
||||
auto aval = wxJoyKeyTextCtrl::ToAccelFromString(val);
|
||||
|
||||
for (size_t i = 0; i < aval.size(); i++)
|
||||
aval[i].Set(aval[i].GetFlags(), aval[i].GetKeyCode(),
|
||||
cmd->cmd_id);
|
||||
aval[i].Set(aval[i].GetUkey(), aval[i].GetJoystick(), aval[i].GetFlags(), aval[i].GetKeyCode(), cmd->cmd_id);
|
||||
|
||||
if (!aval.size())
|
||||
wxLogWarning(_("Invalid key binding %s for %s"), val.c_str(), name.c_str());
|
||||
|
|
|
@ -119,7 +119,7 @@ opt_desc new_opt_desc(wxString opt = wxT(""), const char* cmd = NULL, wxString d
|
|||
|
||||
extern const int num_opts;
|
||||
|
||||
extern const wxAcceleratorEntry default_accels[];
|
||||
extern const wxAcceleratorEntryUnicode default_accels[];
|
||||
extern const int num_def_accels;
|
||||
|
||||
// call to setup default keys.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "drawing.h"
|
||||
#include "filters.h"
|
||||
#include "wxvbam.h"
|
||||
#include "wxutil.h"
|
||||
|
||||
#ifdef __WXMSW__
|
||||
#include <windows.h>
|
||||
|
@ -317,6 +318,7 @@ void GameArea::LoadGame(const wxString& name)
|
|||
emulating = true;
|
||||
was_paused = true;
|
||||
MainFrame* mf = wxGetApp().frame;
|
||||
mf->StopPoll();
|
||||
mf->SetJoystick();
|
||||
mf->cmd_enable &= ~(CMDEN_GB | CMDEN_GBA);
|
||||
mf->cmd_enable |= ONLOAD_CMDEN;
|
||||
|
@ -567,6 +569,7 @@ void GameArea::UnloadGame(bool destruct)
|
|||
mf->enable_menus();
|
||||
mf->SetJoystick();
|
||||
mf->ResetCheatSearch();
|
||||
mf->StartPoll();
|
||||
|
||||
if (rewind_mem)
|
||||
num_rewind_states = 0;
|
||||
|
@ -1032,8 +1035,6 @@ void GameArea::OnIdle(wxIdleEvent& event)
|
|||
wxWindow* w = panel->GetWindow();
|
||||
|
||||
// set up event handlers
|
||||
// use both CHAR_HOOK and KEY_DOWN in case CHAR_HOOK does not work for whatever reason
|
||||
w->Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(GameArea::OnKeyDown), NULL, this);
|
||||
w->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(GameArea::OnKeyDown), NULL, this);
|
||||
w->Connect(wxEVT_KEY_UP, wxKeyEventHandler(GameArea::OnKeyUp), NULL, this);
|
||||
w->Connect(wxEVT_PAINT, wxPaintEventHandler(GameArea::PaintEv), NULL, this);
|
||||
|
@ -1313,28 +1314,19 @@ static void draw_black_background(wxWindow* win) {
|
|||
|
||||
void GameArea::OnKeyDown(wxKeyEvent& ev)
|
||||
{
|
||||
// check if the key is pressed indeed and then process it
|
||||
wxKeyCode keyCode = (wxKeyCode)ev.GetKeyCode();
|
||||
if (wxGetKeyState(keyCode) && process_key_press(true, ev.GetKeyCode(), ev.GetModifiers())) {
|
||||
ev.Skip(false);
|
||||
ev.StopPropagation();
|
||||
int kc = getKeyboardKeyCode(ev);
|
||||
if (process_key_press(true, kc, ev.GetModifiers())) {
|
||||
wxWakeUpIdle();
|
||||
}
|
||||
else {
|
||||
ev.Skip();
|
||||
}
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void GameArea::OnKeyUp(wxKeyEvent& ev)
|
||||
{
|
||||
if (process_key_press(false, ev.GetKeyCode(), ev.GetModifiers())) {
|
||||
ev.Skip(false);
|
||||
ev.StopPropagation();
|
||||
int kc = getKeyboardKeyCode(ev);
|
||||
if (process_key_press(false, kc, ev.GetModifiers())) {
|
||||
wxWakeUpIdle();
|
||||
}
|
||||
else {
|
||||
ev.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
// these three are forwarded to the DrawingPanel instance
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "strutils.h"
|
||||
#include <wx/tokenzr.h>
|
||||
|
||||
// From: https://stackoverflow.com/a/7408245/262458
|
||||
//
|
||||
|
@ -21,6 +22,25 @@ wxArrayString str_split(const wxString& text, const wxString& sep) {
|
|||
return tokens;
|
||||
}
|
||||
|
||||
wxArrayString str_split_with_sep(const wxString& text, const wxString& sep)
|
||||
{
|
||||
wxArrayString tokens;
|
||||
bool sepIsTokenToo = false;
|
||||
wxStringTokenizer tokenizer(text, sep, wxTOKEN_RET_EMPTY_ALL);
|
||||
while (tokenizer.HasMoreTokens()) {
|
||||
wxString token = tokenizer.GetNextToken();
|
||||
if (token.IsEmpty()) {
|
||||
if (!sepIsTokenToo) {
|
||||
sepIsTokenToo = true;
|
||||
tokens.Add(sep);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
tokens.Add(token);
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
size_t vec_find(wxArrayString& opts, const wxString& val) {
|
||||
return opts.Index(val);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
// From: https://stackoverflow.com/a/7408245/262458
|
||||
wxArrayString str_split(const wxString& text, const wxString& sep);
|
||||
|
||||
// Same as above, but it includes the sep dir.
|
||||
// If "A,,,B" is the text and "," is sep, then
|
||||
// 'A', ',' and 'B' will be in the output.
|
||||
wxArrayString str_split_with_sep(const wxString& text, const wxString& sep);
|
||||
|
||||
// From: https://stackoverflow.com/a/15099743/262458
|
||||
size_t vec_find(wxArrayString& opts, const wxString& val);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "viewsupt.h"
|
||||
#include "../common/ConfigManager.h"
|
||||
#include "wxvbam.h"
|
||||
#include "wxutil.h"
|
||||
|
||||
namespace Viewers {
|
||||
void Viewer::CloseDlg(wxCloseEvent& ev)
|
||||
|
@ -415,7 +416,7 @@ void MemView::ShowCaret()
|
|||
|
||||
void MemView::KeyEvent(wxKeyEvent& ev)
|
||||
{
|
||||
uint32_t k = ev.GetKeyCode();
|
||||
uint32_t k = getKeyboardKeyCode(ev);
|
||||
int nnib = 2 << fmt;
|
||||
|
||||
switch (k) {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <wx/tokenzr.h>
|
||||
#include "wx/joyedit.h"
|
||||
#include "strutils.h"
|
||||
|
||||
// FIXME: suppport analog/digital flag on per-axis basis
|
||||
|
||||
|
@ -104,10 +106,10 @@ void wxJoyKeyTextCtrl::OnJoy(wxSDLJoyEvent& event)
|
|||
Navigate();
|
||||
}
|
||||
|
||||
wxString wxJoyKeyTextCtrl::ToString(int mod, int key, int joy)
|
||||
wxString wxJoyKeyTextCtrl::ToString(int mod, int key, int joy, bool isConfig)
|
||||
{
|
||||
if (!joy)
|
||||
return wxKeyTextCtrl::ToString(mod, key);
|
||||
return wxKeyTextCtrl::ToString(mod, key, isConfig);
|
||||
|
||||
wxString s;
|
||||
// Note: wx translates unconditionally (2.8.12, 2.9.1)!
|
||||
|
@ -165,7 +167,7 @@ wxString wxJoyKeyTextCtrl::ToString(int mod, int key, int joy)
|
|||
return s;
|
||||
}
|
||||
|
||||
wxString wxJoyKeyTextCtrl::ToString(wxJoyKeyBinding_v keys, wxChar sep)
|
||||
wxString wxJoyKeyTextCtrl::ToString(wxJoyKeyBinding_v keys, wxChar sep, bool isConfig)
|
||||
{
|
||||
wxString ret;
|
||||
|
||||
|
@ -173,7 +175,26 @@ wxString wxJoyKeyTextCtrl::ToString(wxJoyKeyBinding_v keys, wxChar sep)
|
|||
if (i > 0)
|
||||
ret += sep;
|
||||
|
||||
wxString key = ToString(keys[i].mod, keys[i].key, keys[i].joy);
|
||||
wxString key = ToString(keys[i].mod, keys[i].key, keys[i].joy, isConfig);
|
||||
|
||||
if (key.empty())
|
||||
return wxEmptyString;
|
||||
|
||||
ret += key;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
wxString wxJoyKeyTextCtrl::FromAccelToString(wxAcceleratorEntry_v keys, wxChar sep, bool isConfig)
|
||||
{
|
||||
wxString ret;
|
||||
|
||||
for (size_t i = 0; i < keys.size(); i++) {
|
||||
if (i > 0)
|
||||
ret += sep;
|
||||
|
||||
wxString key = ToString(keys[i].GetFlags(), keys[i].GetKeyCode(), keys[i].GetJoystick(), isConfig);
|
||||
|
||||
if (key.empty())
|
||||
return wxEmptyString;
|
||||
|
@ -262,19 +283,16 @@ static bool ParseJoy(const wxString& s, int len, int& mod, int& key, int& joy)
|
|||
} else if (is_ctrl(hatre)) {
|
||||
hatre.GetMatch(&b, &l, 1);
|
||||
key = simple_atoi(p.Mid(b), l);
|
||||
#define check_dir(n, d) else if (hatre.GetMatch(&b, &l, n) && l > 0) mod = WXJB_HAT_##d
|
||||
|
||||
if (0)
|
||||
;
|
||||
#define check_dir(n, d) if (hatre.GetMatch(&b, &l, n) && l > 0) mod = WXJB_HAT_##d
|
||||
|
||||
check_dir(3, N);
|
||||
check_dir(4, S);
|
||||
check_dir(5, E);
|
||||
check_dir(6, W);
|
||||
check_dir(7, NE);
|
||||
check_dir(8, SE);
|
||||
check_dir(9, SW);
|
||||
check_dir(10, NW);
|
||||
else check_dir(4, S);
|
||||
else check_dir(5, E);
|
||||
else check_dir(6, W);
|
||||
else check_dir(7, NE);
|
||||
else check_dir(8, SE);
|
||||
else check_dir(9, SW);
|
||||
else check_dir(10, NW);
|
||||
} else {
|
||||
joy = 0;
|
||||
return false;
|
||||
|
@ -300,34 +318,30 @@ wxJoyKeyBinding_v wxJoyKeyTextCtrl::FromString(const wxString& s, wxChar sep)
|
|||
{
|
||||
wxJoyKeyBinding_v ret, empty;
|
||||
int mod, key, joy;
|
||||
size_t len = s.size();
|
||||
|
||||
if (!len)
|
||||
if (s.size() == 0)
|
||||
return empty;
|
||||
|
||||
for (size_t lastkey = len - 1; (lastkey = s.rfind(sep, lastkey)) != wxString::npos; lastkey--) {
|
||||
if (lastkey == len - 1) {
|
||||
// sep as accel
|
||||
if (!lastkey)
|
||||
break;
|
||||
|
||||
if (s[lastkey - 1] == wxT('-') || s[lastkey - 1] == wxT('+') || s[lastkey - 1] == sep)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ParseString(s.Mid(lastkey + 1), len - lastkey - 1, mod, key, joy))
|
||||
for (const auto& token : str_split_with_sep(s, sep)) {
|
||||
if (!ParseString(token, token.size(), mod, key, joy))
|
||||
return empty;
|
||||
|
||||
wxJoyKeyBinding jb = { key, mod, joy };
|
||||
ret.insert(ret.begin(), jb);
|
||||
len = lastkey;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!ParseString(s, len, mod, key, joy))
|
||||
wxAcceleratorEntry_v wxJoyKeyTextCtrl::ToAccelFromString(const wxString& s, wxChar sep)
|
||||
{
|
||||
wxAcceleratorEntry_v ret, empty;
|
||||
int mod, key, joy;
|
||||
if (s.size() == 0)
|
||||
return empty;
|
||||
|
||||
wxJoyKeyBinding jb = { key, mod, joy };
|
||||
ret.insert(ret.begin(), jb);
|
||||
for (const auto& token : str_split_with_sep(s, sep)) {
|
||||
if (!ParseString(token, token.size(), mod, key, joy))
|
||||
return empty;
|
||||
ret.insert(ret.begin(), wxAcceleratorEntryUnicode(token, joy, mod, key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,16 @@
|
|||
#include <wx/tokenzr.h>
|
||||
#include <wx/log.h>
|
||||
#include "wx/keyedit.h"
|
||||
#include "strutils.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxKeyTextCtrl, wxTextCtrl)
|
||||
|
||||
BEGIN_EVENT_TABLE(wxKeyTextCtrl, wxTextCtrl)
|
||||
// EVT_CHAR is better than EVT_KEY_DOWN here because it is where
|
||||
// the raw key events will have been cooked using whatever recipes
|
||||
// are in effect from the os, locale, international keyboard
|
||||
// settings, etc. But we shouldn't need it for now, otherwise
|
||||
// we would have problems detecting letter cases.
|
||||
EVT_KEY_DOWN(wxKeyTextCtrl::OnKeyDown)
|
||||
EVT_KEY_UP(wxKeyTextCtrl::OnKeyUp)
|
||||
END_EVENT_TABLE()
|
||||
|
@ -11,7 +18,11 @@ END_EVENT_TABLE()
|
|||
void wxKeyTextCtrl::OnKeyDown(wxKeyEvent& event)
|
||||
{
|
||||
lastmod = event.GetModifiers();
|
||||
lastkey = event.GetKeyCode();
|
||||
lastkey = getKeyboardKeyCode(event);
|
||||
if (lastkey != WXK_NONE) // not a control character
|
||||
{
|
||||
KeyboardInputMap::AddMap(ToCandidateString(lastmod, lastkey), lastkey, lastmod);
|
||||
}
|
||||
}
|
||||
|
||||
void wxKeyTextCtrl::OnKeyUp(wxKeyEvent& event)
|
||||
|
@ -47,7 +58,7 @@ void wxKeyTextCtrl::OnKeyUp(wxKeyEvent& event)
|
|||
} else
|
||||
Clear();
|
||||
} else {
|
||||
wxString nv = ToString(mod, key);
|
||||
wxString nv = ToCandidateString(mod, key);
|
||||
|
||||
if (nv.empty())
|
||||
return;
|
||||
|
@ -66,18 +77,35 @@ void wxKeyTextCtrl::OnKeyUp(wxKeyEvent& event)
|
|||
Navigate();
|
||||
}
|
||||
|
||||
wxString wxKeyTextCtrl::ToString(int mod, int key)
|
||||
wxString wxKeyTextCtrl::ToString(int mod, int key, bool isConfig)
|
||||
{
|
||||
wxString s = ToCandidateString(mod, key);
|
||||
// Check for unicode char. It is not possible to use it for
|
||||
// wxAcceleratorEntry `FromString`
|
||||
wxLogNull disable_logging;
|
||||
wxAcceleratorEntryUnicode aeTest;
|
||||
if (!aeTest.FromString(s) || !s.IsAscii()) {
|
||||
if (!KeyboardInputMap::GetMap(s, key, mod) || isConfig) {
|
||||
wxString unicodeChar;
|
||||
unicodeChar.Printf("%d:%d", key, mod);
|
||||
return unicodeChar;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
wxString wxKeyTextCtrl::ToCandidateString(int mod, int key)
|
||||
{
|
||||
// wx ignores non-alnum printable chars
|
||||
// actually, wx gives an assertion error, so it's best to filter out
|
||||
// before passing to ToString()
|
||||
bool char_override = key > 32 && key < WXK_START && !wxIsalnum(key);
|
||||
bool char_override = key > 32 && key < WXK_START && !wxIsalnum(key) && key != WXK_DELETE;
|
||||
// wx also ignores modifiers (and does not report meta at all)
|
||||
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);
|
||||
wxAcceleratorEntryUnicode 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
|
||||
wxString s = ae.ToString();
|
||||
wxString s = ae.ToRawString();
|
||||
|
||||
if (char_override || mod_override) {
|
||||
size_t l = s.rfind(wxT('-'));
|
||||
|
@ -150,11 +178,10 @@ wxString wxKeyTextCtrl::ToString(int mod, int key)
|
|||
s.Replace(display_name_tr, name_tr, true);
|
||||
s.Replace(display_name, name, true);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
wxString wxKeyTextCtrl::ToString(wxAcceleratorEntry_v keys, wxChar sep)
|
||||
wxString wxKeyTextCtrl::ToString(wxAcceleratorEntry_v keys, wxChar sep, bool isConfig)
|
||||
{
|
||||
wxString ret;
|
||||
|
||||
|
@ -162,7 +189,7 @@ wxString wxKeyTextCtrl::ToString(wxAcceleratorEntry_v keys, wxChar sep)
|
|||
if (i > 0)
|
||||
ret += sep;
|
||||
|
||||
wxString key = ToString(keys[i].GetFlags(), keys[i].GetKeyCode());
|
||||
wxString key = ToString(keys[i].GetFlags(), keys[i].GetKeyCode(), isConfig);
|
||||
|
||||
if (key.empty())
|
||||
return wxEmptyString;
|
||||
|
@ -173,6 +200,21 @@ wxString wxKeyTextCtrl::ToString(wxAcceleratorEntry_v keys, wxChar sep)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool checkForPairKeyMod(const wxString& s, int& mod, int& key)
|
||||
{
|
||||
long ulkey, ulmod;
|
||||
// key:mod as pair
|
||||
auto pair = str_split(s, ":");
|
||||
if (pair.size() == 2 && pair[0].ToLong(&ulkey) && pair[1].ToLong(&ulmod))
|
||||
{
|
||||
key = (int)ulkey;
|
||||
mod = (int)ulmod;
|
||||
KeyboardInputMap::AddMap(wxKeyTextCtrl::ToCandidateString(mod, key), key, mod);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wxKeyTextCtrl::ParseString(const wxString& s, int len, int& mod, int& key)
|
||||
{
|
||||
mod = key = 0;
|
||||
|
@ -180,9 +222,15 @@ bool wxKeyTextCtrl::ParseString(const wxString& s, int len, int& mod, int& key)
|
|||
if (!s || !len)
|
||||
return false;
|
||||
|
||||
if (checkForPairKeyMod(s, mod, key))
|
||||
return true;
|
||||
|
||||
if (KeyboardInputMap::GetMap(s, key, mod))
|
||||
return true;
|
||||
|
||||
wxString a = wxT('\t');
|
||||
a.Append(s.Left(len));
|
||||
wxAcceleratorEntry ae;
|
||||
wxAcceleratorEntryUnicode ae;
|
||||
#ifndef __WXMAC__
|
||||
#define check_meta(str) \
|
||||
do { \
|
||||
|
@ -260,29 +308,12 @@ wxAcceleratorEntry_v wxKeyTextCtrl::FromString(const wxString& s, wxChar sep)
|
|||
{
|
||||
wxAcceleratorEntry_v ret, empty;
|
||||
int mod, key;
|
||||
size_t len = s.size();
|
||||
|
||||
for (size_t lastkey = len - 1; (lastkey = s.rfind(sep, lastkey)) != wxString::npos; lastkey--) {
|
||||
if (lastkey == len - 1) {
|
||||
// sep as accel
|
||||
if (!lastkey)
|
||||
break;
|
||||
|
||||
if (s[lastkey - 1] == wxT('-') || s[lastkey - 1] == wxT('+') || s[lastkey - 1] == sep)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ParseString(s.Mid(lastkey + 1), len - lastkey - 1, mod, key))
|
||||
for (const auto& token : str_split_with_sep(s, sep)) {
|
||||
if (!ParseString(token, token.size(), mod, key))
|
||||
return empty;
|
||||
|
||||
ret.insert(ret.begin(), wxAcceleratorEntry(mod, key));
|
||||
len = lastkey;
|
||||
ret.insert(ret.begin(), wxAcceleratorEntryUnicode(mod, key));
|
||||
}
|
||||
|
||||
if (!ParseString(s, len, mod, key))
|
||||
return empty;
|
||||
|
||||
ret.insert(ret.begin(), wxAcceleratorEntry(mod, key));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,9 +51,9 @@ public:
|
|||
// convert wxSDLJoyEvent's type+val into mod (WXJB_*)
|
||||
static int DigitalButton(wxSDLJoyEvent& event);
|
||||
// convert mod+key to accel string, separated by -
|
||||
static wxString ToString(int mod, int key, int joy);
|
||||
static wxString ToString(int mod, int key, int joy, bool isConfig = false);
|
||||
// convert multiple keys, separated by multikey
|
||||
static wxString ToString(wxJoyKeyBinding_v keys, wxChar sep = wxT(','));
|
||||
static wxString ToString(wxJoyKeyBinding_v keys, wxChar sep = wxT(','), bool isConfig = false);
|
||||
// parses single key string into mod+key
|
||||
static bool FromString(const wxString& s, int& mod, int& key, int& joy);
|
||||
// parse multi-key string into array
|
||||
|
@ -61,6 +61,11 @@ public:
|
|||
static wxJoyKeyBinding_v FromString(const wxString& s, wxChar sep = wxT(','));
|
||||
// parse a single key in given wxChar array up to given len
|
||||
static bool ParseString(const wxString& s, int len, int& mod, int& key, int& joy);
|
||||
// parse multi-key string into array
|
||||
// returns empty array on parse errors
|
||||
static wxAcceleratorEntry_v ToAccelFromString(const wxString& s, wxChar sep = wxT(','));
|
||||
// convert multiple keys, separated by multikey
|
||||
static wxString FromAccelToString(wxAcceleratorEntry_v keys, wxChar sep = wxT(','), bool isConfig = false);
|
||||
|
||||
protected:
|
||||
void OnJoy(wxSDLJoyEvent&);
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
#include <vector>
|
||||
#include <wx/accel.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include "wxutil.h"
|
||||
|
||||
typedef std::vector<wxAcceleratorEntry> wxAcceleratorEntry_v;
|
||||
typedef std::vector<wxAcceleratorEntryUnicode> wxAcceleratorEntry_v;
|
||||
|
||||
class wxKeyTextCtrl : public wxTextCtrl {
|
||||
public:
|
||||
|
@ -51,9 +52,12 @@ public:
|
|||
}
|
||||
|
||||
// convert mod+key to accel string, separated by -
|
||||
static wxString ToString(int mod, int key);
|
||||
static wxString ToString(int mod, int key, bool isConfig = false);
|
||||
// convert multiple keys, separated by multikey
|
||||
static wxString ToString(wxAcceleratorEntry_v keys, wxChar sep = wxT(','));
|
||||
static wxString ToString(wxAcceleratorEntry_v keys, wxChar sep = wxT(','), bool isConfig = false);
|
||||
// convert mod+key to candidate accel string, separated by -
|
||||
// this *should* work, but may fail for unicode chars
|
||||
static wxString ToCandidateString(int mod, int key);
|
||||
// parses single key string into mod+key
|
||||
static bool FromString(const wxString& s, int& mod, int& key);
|
||||
// parse multi-key string into accelentry array
|
||||
|
@ -115,6 +119,7 @@ const struct {
|
|||
wxString display_name;
|
||||
} keys_with_display_names[] = {
|
||||
{ WXK_BACK, wxTRANSLATE("Back"), wxTRANSLATE("Backspace") },
|
||||
{ WXK_DELETE, wxTRANSLATE("Delete"), wxTRANSLATE("Delete") },
|
||||
{ WXK_PAGEUP, wxTRANSLATE("PageUp"), wxTRANSLATE("Page Up") },
|
||||
{ WXK_PAGEDOWN, wxTRANSLATE("PageDown"), wxTRANSLATE("Page Down") },
|
||||
{ WXK_NUMLOCK, wxTRANSLATE("Num_lock"), wxTRANSLATE("Num Lock") },
|
||||
|
|
|
@ -65,8 +65,11 @@
|
|||
|
||||
#include "wx/keyedit.h"
|
||||
|
||||
static inline void DoSetAccel(wxMenuItem* mi, wxAcceleratorEntry* acc)
|
||||
static inline void DoSetAccel(wxMenuItem* mi, wxAcceleratorEntryUnicode* acc)
|
||||
{
|
||||
// cannot use SDL keybinding as text without wx assertion error
|
||||
if (!acc || acc->GetJoystick() != 0) return;
|
||||
|
||||
wxString lab = mi->GetItemLabel();
|
||||
size_t tab = lab.find(wxT('\t'));
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
#include "wxutil.h"
|
||||
#include "../common/contains.h"
|
||||
|
||||
|
||||
int getKeyboardKeyCode(wxKeyEvent& event)
|
||||
{
|
||||
int uc = event.GetUnicodeKey();
|
||||
if (uc != WXK_NONE) {
|
||||
if (uc < 32)
|
||||
return WXK_NONE;
|
||||
return uc;
|
||||
}
|
||||
else {
|
||||
return event.GetKeyCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wxAcceleratorEntryUnicode::wxAcceleratorEntryUnicode(wxAcceleratorEntry *accel)
|
||||
: wxAcceleratorEntry(accel->GetFlags(), accel->GetKeyCode(), accel->GetCommand(), accel->GetMenuItem())
|
||||
{
|
||||
init(accel->GetFlags(), accel->GetKeyCode());
|
||||
}
|
||||
|
||||
|
||||
wxAcceleratorEntryUnicode::wxAcceleratorEntryUnicode(int flags, int keyCode, int cmd, wxMenuItem *item)
|
||||
: wxAcceleratorEntry(flags, keyCode, cmd, item)
|
||||
{
|
||||
init(flags, keyCode);
|
||||
}
|
||||
|
||||
|
||||
wxAcceleratorEntryUnicode::wxAcceleratorEntryUnicode(wxString uKey, int joy, int flags, int keyCode, int cmd, wxMenuItem *item)
|
||||
: wxAcceleratorEntry(flags, keyCode, cmd, item)
|
||||
{
|
||||
ukey = uKey;
|
||||
joystick = joy;
|
||||
}
|
||||
|
||||
|
||||
void wxAcceleratorEntryUnicode::Set(wxString uKey, int joy, int flags, int keyCode, int cmd, wxMenuItem *item)
|
||||
{
|
||||
ukey = uKey;
|
||||
joystick = joy;
|
||||
wxAcceleratorEntry::Set(flags, keyCode, cmd, item);
|
||||
}
|
||||
|
||||
|
||||
void wxAcceleratorEntryUnicode::init(int flags, int keyCode)
|
||||
{
|
||||
joystick = 0;
|
||||
if (!(flags == 0 && keyCode == 0)) {
|
||||
ukey.Printf("%d:%d", keyCode, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KeyboardInputMap* KeyboardInputMap::getInstance()
|
||||
{
|
||||
static KeyboardInputMap instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
|
||||
KeyboardInputMap::KeyboardInputMap(){}
|
||||
|
||||
|
||||
void KeyboardInputMap::AddMap(wxString keyStr, int key, int mod)
|
||||
{
|
||||
KeyboardInputMap* singleton = getInstance();
|
||||
singleton->keysMap[keyStr.wc_str()] = singleton->newPair(key, mod);
|
||||
}
|
||||
|
||||
|
||||
bool KeyboardInputMap::GetMap(wxString keyStr, int &key, int &mod)
|
||||
{
|
||||
KeyboardInputMap* singleton = getInstance();
|
||||
if (contains(singleton->keysMap, keyStr.wc_str())) {
|
||||
key = singleton->keysMap.at(keyStr.wc_str()).key;
|
||||
mod = singleton->keysMap.at(keyStr.wc_str()).mod;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#ifndef _WX_UTIL_H
|
||||
#define _WX_UTIL_H
|
||||
|
||||
#include <wx/event.h>
|
||||
|
||||
int getKeyboardKeyCode(wxKeyEvent& event);
|
||||
|
||||
#include <wx/accel.h>
|
||||
|
||||
class wxAcceleratorEntryUnicode : public wxAcceleratorEntry
|
||||
{
|
||||
public:
|
||||
wxAcceleratorEntryUnicode(wxAcceleratorEntry *accel);
|
||||
wxAcceleratorEntryUnicode(int flags=0, int keyCode=0, int cmd=0, wxMenuItem *item=nullptr);
|
||||
wxAcceleratorEntryUnicode(wxString uKey, int joy=0, int flags=0, int keyCode=0, int cmd=0, wxMenuItem *item=nullptr);
|
||||
|
||||
void Set(wxString uKey, int joy, int flags, int keyCode, int cmd, wxMenuItem *item=nullptr);
|
||||
|
||||
int GetJoystick() const { return joystick; };
|
||||
wxString GetUkey() const { return ukey; };
|
||||
private:
|
||||
void init(int flags, int keyCode);
|
||||
wxString ukey;
|
||||
int joystick;
|
||||
};
|
||||
|
||||
#include <unordered_map>
|
||||
#include <wx/string.h>
|
||||
#include "widgets/wx/keyedit.h"
|
||||
|
||||
class KeyboardInputMap
|
||||
{
|
||||
public:
|
||||
static KeyboardInputMap* getInstance();
|
||||
static void AddMap(wxString keyStr, int key, int mod);
|
||||
static bool GetMap(wxString keyStr, int &key, int &mod);
|
||||
private:
|
||||
KeyboardInputMap();
|
||||
|
||||
// We want to keep track of this pair for
|
||||
// almost all keypresses.
|
||||
typedef struct KeyMod {
|
||||
int key;
|
||||
int mod;
|
||||
} KeyMod;
|
||||
|
||||
KeyMod newPair(int key, int mod)
|
||||
{
|
||||
KeyMod tmp;
|
||||
tmp.key = key;
|
||||
tmp.mod = mod;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Map accel string to pair
|
||||
std::unordered_map<std::wstring, KeyMod> keysMap;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -720,6 +720,8 @@ MainFrame::MainFrame()
|
|||
, dialog_opened(0)
|
||||
, focused(false)
|
||||
{
|
||||
jpoll = new JoystickPoller();
|
||||
this->Connect(wxID_ANY, wxEVT_SHOW, wxShowEventHandler(JoystickPoller::ShowDialog), jpoll, jpoll);
|
||||
}
|
||||
|
||||
MainFrame::~MainFrame()
|
||||
|
@ -846,7 +848,7 @@ int MainFrame::FilterEvent(wxEvent& event)
|
|||
if (event.GetEventType() == wxEVT_KEY_DOWN && !menus_opened && !dialog_opened)
|
||||
{
|
||||
wxKeyEvent& ke = (wxKeyEvent&)event;
|
||||
int keyCode = ke.GetKeyCode();
|
||||
int keyCode = getKeyboardKeyCode(ke);
|
||||
int keyMod = ke.GetModifiers();
|
||||
wxAcceleratorEntry_v accels = wxGetApp().GetAccels();
|
||||
for (size_t i = 0; i < accels.size(); ++i)
|
||||
|
@ -858,6 +860,25 @@ int MainFrame::FilterEvent(wxEvent& event)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
else if (event.GetEventType() == wxEVT_SDLJOY && !menus_opened && !dialog_opened)
|
||||
{
|
||||
wxSDLJoyEvent& je = (wxSDLJoyEvent&)event;
|
||||
if (je.GetControlValue() == 0) return -1; // joystick button UP
|
||||
int key = je.GetControlIndex();
|
||||
int mod = wxJoyKeyTextCtrl::DigitalButton(je);
|
||||
int joy = je.GetJoy() + 1;
|
||||
wxString label = wxJoyKeyTextCtrl::ToString(mod, key, joy);
|
||||
wxAcceleratorEntry_v accels = wxGetApp().GetAccels();
|
||||
for (size_t i = 0; i < accels.size(); ++i) {
|
||||
if (label == accels[i].GetUkey())
|
||||
{
|
||||
wxCommandEvent evh(wxEVT_COMMAND_MENU_SELECTED, accels[i].GetCommand());
|
||||
evh.SetEventObject(this);
|
||||
GetEventHandler()->ProcessEvent(evh);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -886,31 +907,39 @@ wxString MainFrame::GetGamePath(wxString path)
|
|||
|
||||
void MainFrame::SetJoystick()
|
||||
{
|
||||
bool anyjoy = false;
|
||||
/* Remove all attached joysticks to avoid errors while
|
||||
* destroying and creating the GameArea `panel`. */
|
||||
joy.Remove();
|
||||
|
||||
set_global_accels();
|
||||
|
||||
if (!emulating)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
for (int j = 0; j < NUM_KEYS; j++) {
|
||||
wxJoyKeyBinding_v b = gopts.joykey_bindings[i][j];
|
||||
|
||||
for (size_t k = 0; k < b.size(); k++) {
|
||||
int jn = b[k].joy;
|
||||
|
||||
if (jn) {
|
||||
if (!anyjoy) {
|
||||
anyjoy = true;
|
||||
joy.Attach(panel);
|
||||
}
|
||||
|
||||
joy.Add(jn - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainFrame::StopPoll()
|
||||
{
|
||||
if (jpoll && jpoll->IsRunning())
|
||||
jpoll->Stop();
|
||||
}
|
||||
|
||||
void MainFrame::StartPoll()
|
||||
{
|
||||
if (jpoll && !jpoll->IsRunning())
|
||||
jpoll->Start();
|
||||
}
|
||||
|
||||
void MainFrame::enable_menus()
|
||||
{
|
||||
for (int i = 0; i < ncmds; i++)
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "../gba/Sound.h"
|
||||
|
||||
#include "wxlogdebug.h"
|
||||
#include "wxutil.h"
|
||||
|
||||
template <typename T>
|
||||
void CheckPointer(T pointer)
|
||||
|
@ -203,6 +204,8 @@ class GameArea;
|
|||
|
||||
class LogDialog;
|
||||
|
||||
class JoystickPoller;
|
||||
|
||||
// true if pause should happen at next frame
|
||||
extern bool pause_next;
|
||||
|
||||
|
@ -320,6 +323,10 @@ public:
|
|||
|
||||
void PollJoysticks() { joy.Poll(); }
|
||||
|
||||
// poll joysticks with timer
|
||||
void StopPoll();
|
||||
void StartPoll();
|
||||
|
||||
// required for building from xrc
|
||||
DECLARE_DYNAMIC_CLASS(MainFrame);
|
||||
// required for event handling
|
||||
|
@ -345,9 +352,10 @@ private:
|
|||
checkable_mi_array_t checkable_mi;
|
||||
// recent menu item accels
|
||||
wxMenu* recent;
|
||||
wxAcceleratorEntry recent_accel[10];
|
||||
wxAcceleratorEntryUnicode recent_accel[10];
|
||||
// joystick reader
|
||||
wxSDLJoy joy;
|
||||
JoystickPoller* jpoll = nullptr;
|
||||
|
||||
// helper function for adding menu to accel editor
|
||||
void add_menu_accels(wxTreeCtrl* tc, wxTreeItemId& parent, wxMenu* menu);
|
||||
|
@ -383,6 +391,20 @@ private:
|
|||
double hidpi_scale_factor;
|
||||
};
|
||||
|
||||
// a class for polling joystick keys
|
||||
class JoystickPoller : public wxTimer {
|
||||
public:
|
||||
void Notify() {
|
||||
wxGetApp().frame->PollJoysticks();
|
||||
}
|
||||
void ShowDialog(wxShowEvent& ev) {
|
||||
if (ev.IsShown())
|
||||
Start(50);
|
||||
else
|
||||
Stop();
|
||||
}
|
||||
};
|
||||
|
||||
// a helper class to avoid forgetting StopModal()
|
||||
class ModalPause {
|
||||
public:
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
<border>5</border>
|
||||
</object>
|
||||
<object class="sizeritem">
|
||||
<object class="wxTextCtrl" name="Shortcut" subclass="wxKeyTextCtrl">
|
||||
<object class="wxTextCtrl" name="Shortcut" subclass="wxJoyKeyTextCtrl">
|
||||
<style>wxTE_PROCESS_ENTER|wxTE_PROCESS_TAB</style>
|
||||
</object>
|
||||
<flag>wxALL|wxEXPAND</flag>
|
||||
|
|
Loading…
Reference in New Issue