From 61c04de7ee24ab7dcb297a37090c6a622b7f3af6 Mon Sep 17 00:00:00 2001 From: skidau Date: Tue, 27 Jan 2015 12:24:47 +1100 Subject: [PATCH] Added the ability to map gamepad buttons to hotkeys. --- Source/Core/Core/CMakeLists.txt | 1 + Source/Core/Core/Core.vcxproj | 2 + Source/Core/Core/Core.vcxproj.filters | 2 + Source/Core/Core/HotkeyManager.cpp | 546 ++++++++++++++++++ Source/Core/Core/HotkeyManager.h | 41 ++ Source/Core/DolphinWX/ConfigMain.cpp | 34 +- Source/Core/DolphinWX/Frame.cpp | 456 ++++++++------- Source/Core/DolphinWX/Frame.h | 11 + Source/Core/DolphinWX/FrameTools.cpp | 41 +- Source/Core/DolphinWX/Globals.h | 1 + Source/Core/DolphinWX/HotkeyDlg.cpp | 212 +++---- Source/Core/DolphinWX/HotkeyDlg.h | 2 +- Source/Core/DolphinWX/InputConfigDiag.cpp | 3 +- .../Core/DolphinWX/InputConfigDiagBitmaps.cpp | 4 +- 14 files changed, 1048 insertions(+), 308 deletions(-) create mode 100644 Source/Core/Core/HotkeyManager.cpp create mode 100644 Source/Core/Core/HotkeyManager.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 4f7176185e..442d339ba0 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -9,6 +9,7 @@ set(SRCS ActionReplay.cpp ec_wii.cpp GeckoCodeConfig.cpp GeckoCode.cpp + HotkeyManager.cpp MemTools.cpp Movie.cpp NetPlayClient.cpp diff --git a/Source/Core/Core/Core.vcxproj b/Source/Core/Core/Core.vcxproj index 23f0167763..d7e63a5759 100644 --- a/Source/Core/Core/Core.vcxproj +++ b/Source/Core/Core/Core.vcxproj @@ -94,6 +94,7 @@ + @@ -305,6 +306,7 @@ + diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index 3fc6e92433..ceb6c77cf7 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -144,6 +144,7 @@ + @@ -732,6 +733,7 @@ + diff --git a/Source/Core/Core/HotkeyManager.cpp b/Source/Core/Core/HotkeyManager.cpp new file mode 100644 index 0000000000..431ff1696f --- /dev/null +++ b/Source/Core/Core/HotkeyManager.cpp @@ -0,0 +1,546 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "Core/ConfigManager.h" +#include "Core/CoreParameter.h" +#include "Core/HotkeyManager.h" + +static const u32 hotkey_bitmasks[] = +{ + 1 << 0, + 1 << 1, + 1 << 2, + 1 << 3, + 1 << 4, + 1 << 5, + 1 << 6, + 1 << 7, + 1 << 8, + 1 << 9, + 1 << 10, + 1 << 11, + 1 << 12, + 1 << 13, + 1 << 14, + 1 << 15, + 1 << 16, + 1 << 17, + 1 << 18, + 1 << 19, + 1 << 20, + 1 << 21, + 1 << 22, + 1 << 23, + 1 << 24, + 1 << 25, + 1 << 26, + 1 << 27, + 1 << 28, + 1 << 29, + 1 << 30, + 1u << 31u +}; + +const std::string hotkey_labels[] = +{ + _trans("Open"), + _trans("Change Disc"), + _trans("Refresh List"), + + _trans("Play/Pause"), + _trans("Stop"), + _trans("Reset"), + _trans("Frame Advance"), + + _trans("Start Recording"), + _trans("Play Recording"), + _trans("Export Recording"), + _trans("Read-only mode"), + + _trans("Toggle Fullscreen"), + _trans("Take Screenshot"), + _trans("Exit"), + + _trans("Connect Wiimote 1"), + _trans("Connect Wiimote 2"), + _trans("Connect Wiimote 3"), + _trans("Connect Wiimote 4"), + _trans("Connect Balance Board"), + + _trans("Volume Up"), + _trans("Volume Down"), + _trans("Volume Toggle Mute"), + + _trans("Toggle IR"), + _trans("Toggle Aspect Ratio"), + _trans("Toggle EFB Copies"), + _trans("Toggle Fog"), + _trans("Toggle Frame limit"), + _trans("Increase Frame limit"), + _trans("Decrease Frame limit"), + + _trans("Freelook Decrease Speed"), + _trans("Freelook Increase Speed"), + _trans("Freelook Reset Speed"), + _trans("Freelook Move Up"), + _trans("Freelook Move Down"), + _trans("Freelook Move Left"), + _trans("Freelook Move Right"), + _trans("Freelook Zoom In"), + _trans("Freelook Zoom Out"), + _trans("Freelook Reset"), + + _trans("Increase Depth"), + _trans("Decrease Depth"), + _trans("Increase Convergence"), + _trans("Decrease Convergence"), + + _trans("Load State Slot 1"), + _trans("Load State Slot 2"), + _trans("Load State Slot 3"), + _trans("Load State Slot 4"), + _trans("Load State Slot 5"), + _trans("Load State Slot 6"), + _trans("Load State Slot 7"), + _trans("Load State Slot 8"), + _trans("Load State Slot 9"), + _trans("Load State Slot 10"), + + _trans("Save State Slot 1"), + _trans("Save State Slot 2"), + _trans("Save State Slot 3"), + _trans("Save State Slot 4"), + _trans("Save State Slot 5"), + _trans("Save State Slot 6"), + _trans("Save State Slot 7"), + _trans("Save State Slot 8"), + _trans("Save State Slot 9"), + _trans("Save State Slot 10"), + + _trans("Select State Slot 1"), + _trans("Select State Slot 2"), + _trans("Select State Slot 3"), + _trans("Select State Slot 4"), + _trans("Select State Slot 5"), + _trans("Select State Slot 6"), + _trans("Select State Slot 7"), + _trans("Select State Slot 8"), + _trans("Select State Slot 9"), + _trans("Select State Slot 10"), + + _trans("Save to selected slot"), + _trans("Load from selected slot"), + + _trans("Load State Last 1"), + _trans("Load State Last 2"), + _trans("Load State Last 3"), + _trans("Load State Last 4"), + _trans("Load State Last 5"), + _trans("Load State Last 6"), + _trans("Load State Last 7"), + _trans("Load State Last 8"), + + _trans("Save Oldest State"), + _trans("Undo Load State"), + _trans("Undo Save State"), + _trans("Save State"), + _trans("Load State"), +}; + +const int num_hotkeys = (sizeof(hotkey_labels) / sizeof(hotkey_labels[0])); + +namespace HotkeyManagerEmu +{ + +static InputConfig s_config("Hotkeys", _trans("Hotkeys"), "Hotkeys"); +InputConfig* GetConfig() +{ + return &s_config; +} + +void GetStatus(u8 _port, HotkeyStatus* _pHotkeyStatus) +{ + memset(_pHotkeyStatus, 0, sizeof(*_pHotkeyStatus)); + _pHotkeyStatus->err = PAD_ERR_NONE; + + std::unique_lock lk(s_config.controls_lock, std::try_to_lock); + + if (!lk.owns_lock()) + { + // if gui has lock (messing with controls), skip this input cycle + for (int i = 0; i < 6; i++) + _pHotkeyStatus->button[i] = 0; + + return; + } + + // get input + ((HotkeyManager*)s_config.controllers[_port])->GetInput(_pHotkeyStatus); +} + +bool IsPressed(int Id, bool held) +{ + HotkeyStatus hotkey; + memset(&hotkey, 0, sizeof(hotkey)); + GetStatus(0, &hotkey); + unsigned int set = Id / 32; + unsigned int setKey = Id % 32; + if (hotkey.button[set] & (1 << setKey)) + { + hotkeyDown[set] |= (1 << setKey); + if (held) + return true; + } + else + { + bool pressed = !!(hotkeyDown[set] & (1 << setKey)); + hotkeyDown[set] &= ~(1 << setKey); + if (pressed) + return true; + } + + return false; +} + +void Initialize(void* const hwnd) +{ + s_config.controllers.push_back(new HotkeyManager()); + + g_controller_interface.Initialize(hwnd); + + // load the saved controller config + s_config.LoadConfig(true); + + for (unsigned int i = 0; i < 6; ++i) + hotkeyDown[i] = 0; +} + +void Shutdown() +{ + std::vector::const_iterator + i = s_config.controllers.begin(), + e = s_config.controllers.end(); + for (; i != e; ++i) + delete *i; + s_config.controllers.clear(); + + g_controller_interface.Shutdown(); +} + +} + +HotkeyManager::HotkeyManager() +{ + for (int set = 0; set < 6; set++) + { + // buttons + if ((set * 32) < num_hotkeys) + groups.emplace_back(m_keys[set] = new Buttons(_trans("Keys"))); + + for (int key = 0; key < 32; key++) + { + if ((set * 32 + key) < num_hotkeys) + { + m_keys[set]->controls.emplace_back(new ControlGroup::Input(hotkey_labels[set * 32 + key])); + } + } + } + + groups.emplace_back(m_options = new ControlGroup(_trans("Options"))); + m_options->settings.emplace_back(new ControlGroup::BackgroundInputSetting(_trans("Background Input"))); + m_options->settings.emplace_back(new ControlGroup::IterateUI(_trans("Iterative Input"))); +} + +HotkeyManager::~HotkeyManager() +{ +} + +std::string HotkeyManager::GetName() const +{ + return std::string("Hotkeys") + char('1' + 0); +} + +void HotkeyManager::GetInput(HotkeyStatus* const kb) +{ + for (int set = 0; set < 6; set++) + if ((set * 32) < num_hotkeys) + m_keys[set]->GetState(&kb->button[set], hotkey_bitmasks); +} + +void HotkeyManager::LoadDefaults(const ControllerInterface& ciface) +{ +#define set_control(group, num, str) (group)->controls[num]->control_ref->expression = (str) + + ControllerEmu::LoadDefaults(ciface); + + // Buttons +#ifdef _WIN32 + set_control(m_keys[0], 0, "(LCONTROL | RCONTROL) & L"); // Open + set_control(m_keys[0], 1, ""); // ChangeDisc + set_control(m_keys[0], 2, ""); // RefreshList + set_control(m_keys[0], 3, "F10"); // PlayPause + set_control(m_keys[0], 4, "ESCAPE"); // Stop + set_control(m_keys[0], 5, ""); // Reset + set_control(m_keys[0], 6, ""); // FrameAdvance + set_control(m_keys[0], 7, ""); // StartRecording + set_control(m_keys[0], 8, ""); // PlayRecording + set_control(m_keys[0], 9, ""); // ExportRecording + set_control(m_keys[0], 10, ""); // Readonlymode + set_control(m_keys[0], 11, "(LMENU | RMENU) & RETURN"); // ToggleFullscreen + set_control(m_keys[0], 12, "`F9` & !(LMENU | RMENU)"); // Screenshot + set_control(m_keys[0], 13, ""); // Exit + set_control(m_keys[0], 14, "(LMENU | RMENU) & `F5`"); // Wiimote1Connect + set_control(m_keys[0], 15, "(LMENU | RMENU) & `F6`"); // Wiimote2Connect + set_control(m_keys[0], 16, "(LMENU | RMENU) & `F7`"); // Wiimote3Connect + set_control(m_keys[0], 17, "(LMENU | RMENU) & `F8`"); // Wiimote4Connect + set_control(m_keys[0], 18, "(LMENU | RMENU) & `F9`"); // BalanceBoardConnect + set_control(m_keys[0], 19, ""); // VolumeDown + set_control(m_keys[0], 20, ""); // VolumeUp + set_control(m_keys[0], 21, ""); // VolumeToggleMute + set_control(m_keys[0], 22, ""); // ToggleIR + set_control(m_keys[0], 23, ""); // ToggleAspectRatio + set_control(m_keys[0], 24, ""); // ToggleEFBCopies + set_control(m_keys[0], 25, ""); // ToggleFog + set_control(m_keys[0], 26, "TAB"); // ToggleThrottle + set_control(m_keys[0], 27, ""); // DecreaseFrameLimit + set_control(m_keys[0], 28, ""); // IncreaseFrameLimit + set_control(m_keys[0], 29, "1"); // FreelookDecreaseSpeed + set_control(m_keys[0], 30, "2"); // FreelookIncreaseSpeed + set_control(m_keys[0], 31, "F"); // FreelookResetSpeed + set_control(m_keys[1], 0, "E"); // FreelookUp + set_control(m_keys[1], 1, "Q"); // FreelookDown + set_control(m_keys[1], 2, "A"); // FreelookLeft + set_control(m_keys[1], 3, "D"); // FreelookRight + set_control(m_keys[1], 4, "W"); // FreelookZoomIn + set_control(m_keys[1], 5, "S"); // FreelookZoomOut + set_control(m_keys[1], 6, "R"); // FreelookReset + set_control(m_keys[1], 7, ""); // DecreaseDepth + set_control(m_keys[1], 8, ""); // IncreaseDepth + set_control(m_keys[1], 9, ""); // DecreaseConvergence + set_control(m_keys[1], 10, ""); // IncreaseConvergence + set_control(m_keys[1], 11, "`F1` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot1 + set_control(m_keys[1], 12, "`F2` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot2 + set_control(m_keys[1], 13, "`F3` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot3 + set_control(m_keys[1], 14, "`F4` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot4 + set_control(m_keys[1], 15, "`F5` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot5 + set_control(m_keys[1], 16, "`F6` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot6 + set_control(m_keys[1], 17, "`F7` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot7 + set_control(m_keys[1], 18, "`F8` & !(LSHIFT | RSHIFT) & !(LMENU | RMENU)"); // LoadStateSlot8 + set_control(m_keys[1], 19, ""); // LoadStateSlot9 + set_control(m_keys[1], 20, ""); // LoadStateSlot10 + set_control(m_keys[1], 21, "(LSHIFT | RSHIFT) & `F1`"); // SaveStateSlot1 + set_control(m_keys[1], 22, "(LSHIFT | RSHIFT) & `F2`"); // SaveStateSlot2 + set_control(m_keys[1], 23, "(LSHIFT | RSHIFT) & `F3`"); // SaveStateSlot3 + set_control(m_keys[1], 24, "(LSHIFT | RSHIFT) & `F4`"); // SaveStateSlot4 + set_control(m_keys[1], 25, "(LSHIFT | RSHIFT) & `F5`"); // SaveStateSlot5 + set_control(m_keys[1], 26, "(LSHIFT | RSHIFT) & `F6`"); // SaveStateSlot6 + set_control(m_keys[1], 27, "(LSHIFT | RSHIFT) & `F7`"); // SaveStateSlot7 + set_control(m_keys[1], 28, "(LSHIFT | RSHIFT) & `F8`"); // SaveStateSlot8 + set_control(m_keys[1], 29, ""); // SaveStateSlot9 + set_control(m_keys[1], 30, ""); // SaveStateSlot10 + set_control(m_keys[1], 31, ""); // SelectStateSlot1 + set_control(m_keys[2], 0, ""); // SelectStateSlot2 + set_control(m_keys[2], 1, ""); // SelectStateSlot3 + set_control(m_keys[2], 2, ""); // SelectStateSlot4 + set_control(m_keys[2], 3, ""); // SelectStateSlot5 + set_control(m_keys[2], 4, ""); // SelectStateSlot6 + set_control(m_keys[2], 5, ""); // SelectStateSlot7 + set_control(m_keys[2], 6, ""); // SelectStateSlot8 + set_control(m_keys[2], 7, ""); // SelectStateSlot9 + set_control(m_keys[2], 8, ""); // SelectStateSlot10 + set_control(m_keys[2], 9, ""); // SaveSelectedSlot + set_control(m_keys[2], 10, ""); // LoadSelectedSlot + set_control(m_keys[2], 11, ""); // LoadLastState1 + set_control(m_keys[2], 12, ""); // LoadLastState2 + set_control(m_keys[2], 13, ""); // LoadLastState3 + set_control(m_keys[2], 14, ""); // LoadLastState4 + set_control(m_keys[2], 15, ""); // LoadLastState5 + set_control(m_keys[2], 16, ""); // LoadLastState6 + set_control(m_keys[2], 17, ""); // LoadLastState7 + set_control(m_keys[2], 18, ""); // LoadLastState8 + set_control(m_keys[2], 19, ""); // SaveFirstState + set_control(m_keys[2], 20, "`F12` & !(LSHIFT | RSHIFT)"); // UndoLoadState + set_control(m_keys[2], 21, "(LSHIFT | RSHIFT) & `F12`"); // UndoSaveState + set_control(m_keys[2], 22, ""); // SaveStateFile + set_control(m_keys[2], 23, ""); // LoadStateFile +#elif __APPLE__ + set_control(m_keys[0], 0, "(`Left Command` | `Right Command`) & `O`"); // Open + set_control(m_keys[0], 1, ""); // ChangeDisc + set_control(m_keys[0], 2, ""); // RefreshList + set_control(m_keys[0], 3, "(`Left Command` | `Right Command`) & `P`"); // PlayPause + set_control(m_keys[0], 4, "(`Left Command` | `Right Command`) & `W`"); // Stop + set_control(m_keys[0], 5, ""); // Reset + set_control(m_keys[0], 6, ""); // FrameAdvance + set_control(m_keys[0], 7, ""); // StartRecording + set_control(m_keys[0], 8, ""); // PlayRecording + set_control(m_keys[0], 9, ""); // ExportRecording + set_control(m_keys[0], 10, ""); // Readonlymode + set_control(m_keys[0], 11, "(`Left Command` | `Right Command`) & `F`"); // ToggleFullscreen + set_control(m_keys[0], 12, "(`Left Command` | `Right Command`) & `S`"); // Screenshot + set_control(m_keys[0], 13, ""); // Exit + set_control(m_keys[0], 14, "(`Left Command` | `Right Command`) & `1`"); // Wiimote1Connect + set_control(m_keys[0], 15, "(`Left Command` | `Right Command`) & `2`"); // Wiimote2Connect + set_control(m_keys[0], 16, "(`Left Command` | `Right Command`) & `3`"); // Wiimote3Connect + set_control(m_keys[0], 17, "(`Left Command` | `Right Command`) & `4`"); // Wiimote4Connect + set_control(m_keys[0], 18, "(`Left Command` | `Right Command`) & `5`"); // BalanceBoardConnect + set_control(m_keys[0], 19, ""); // VolumeDown + set_control(m_keys[0], 20, ""); // VolumeUp + set_control(m_keys[0], 21, ""); // VolumeToggleMute + set_control(m_keys[0], 22, ""); // ToggleIR + set_control(m_keys[0], 23, ""); // ToggleAspectRatio + set_control(m_keys[0], 24, ""); // ToggleEFBCopies + set_control(m_keys[0], 25, ""); // ToggleFog + set_control(m_keys[0], 26, "Tab"); // ToggleThrottle + set_control(m_keys[0], 27, ""); // DecreaseFrameLimit + set_control(m_keys[0], 28, ""); // IncreaseFrameLimit + set_control(m_keys[0], 29, "`1` & !(`Left Command` | `Right Command`)"); // FreelookDecreaseSpeed + set_control(m_keys[0], 30, "`2` & !(`Left Command` | `Right Command`)"); // FreelookIncreaseSpeed + set_control(m_keys[0], 31, "`F` & !(`Left Command` | `Right Command`)"); // FreelookResetSpeed + set_control(m_keys[1], 0, "`E` & !(`Left Command` | `Right Command`)"); // FreelookUp + set_control(m_keys[1], 1, "`Q` & !(`Left Command` | `Right Command`)"); // FreelookDown + set_control(m_keys[1], 2, "`A` & !(`Left Command` | `Right Command`)"); // FreelookLeft + set_control(m_keys[1], 3, "`D` & !(`Left Command` | `Right Command`)"); // FreelookRight + set_control(m_keys[1], 4, "`W` & !(`Left Command` | `Right Command`)"); // FreelookZoomIn + set_control(m_keys[1], 5, "`S` & !(`Left Command` | `Right Command`)"); // FreelookZoomOut + set_control(m_keys[1], 6, "`R` & !(`Left Command` | `Right Command`)"); // FreelookReset + set_control(m_keys[1], 7, ""); // DecreaseDepth + set_control(m_keys[1], 8, ""); // IncreaseDepth + set_control(m_keys[1], 9, ""); // DecreaseConvergence + set_control(m_keys[1], 10, ""); // IncreaseConvergence + set_control(m_keys[1], 11, "`F1` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot1 + set_control(m_keys[1], 12, "`F2` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot2 + set_control(m_keys[1], 13, "`F3` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot3 + set_control(m_keys[1], 14, "`F4` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot4 + set_control(m_keys[1], 15, "`F5` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot5 + set_control(m_keys[1], 16, "`F6` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot6 + set_control(m_keys[1], 17, "`F7` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot7 + set_control(m_keys[1], 18, "`F8` & !(`Left Shift` | `Right Shift`)"); // LoadStateSlot8 + set_control(m_keys[1], 19, ""); // LoadStateSlot9 + set_control(m_keys[1], 20, ""); // LoadStateSlot10 + set_control(m_keys[1], 21, "(`Left Shift` | `Right Shift`) & `F1`"); // SaveStateSlot1 + set_control(m_keys[1], 22, "(`Left Shift` | `Right Shift`) & `F2`"); // SaveStateSlot2 + set_control(m_keys[1], 23, "(`Left Shift` | `Right Shift`) & `F3`"); // SaveStateSlot3 + set_control(m_keys[1], 24, "(`Left Shift` | `Right Shift`) & `F4`"); // SaveStateSlot4 + set_control(m_keys[1], 25, "(`Left Shift` | `Right Shift`) & `F5`"); // SaveStateSlot5 + set_control(m_keys[1], 26, "(`Left Shift` | `Right Shift`) & `F6`"); // SaveStateSlot6 + set_control(m_keys[1], 27, "(`Left Shift` | `Right Shift`) & `F7`"); // SaveStateSlot7 + set_control(m_keys[1], 28, "(`Left Shift` | `Right Shift`) & `F8`"); // SaveStateSlot8 + set_control(m_keys[1], 29, ""); // SaveStateSlot9 + set_control(m_keys[1], 30, ""); // SaveStateSlot10 + set_control(m_keys[1], 31, ""); // SelectStateSlot1 + set_control(m_keys[2], 0, ""); // SelectStateSlot2 + set_control(m_keys[2], 1, ""); // SelectStateSlot3 + set_control(m_keys[2], 2, ""); // SelectStateSlot4 + set_control(m_keys[2], 3, ""); // SelectStateSlot5 + set_control(m_keys[2], 4, ""); // SelectStateSlot6 + set_control(m_keys[2], 5, ""); // SelectStateSlot7 + set_control(m_keys[2], 6, ""); // SelectStateSlot8 + set_control(m_keys[2], 7, ""); // SelectStateSlot9 + set_control(m_keys[2], 8, ""); // SelectStateSlot10 + set_control(m_keys[2], 9, ""); // SaveSelectedSlot + set_control(m_keys[2], 10, ""); // LoadSelectedSlot + set_control(m_keys[2], 11, ""); // LoadLastState1 + set_control(m_keys[2], 12, ""); // LoadLastState2 + set_control(m_keys[2], 13, ""); // LoadLastState3 + set_control(m_keys[2], 14, ""); // LoadLastState4 + set_control(m_keys[2], 15, ""); // LoadLastState5 + set_control(m_keys[2], 16, ""); // LoadLastState6 + set_control(m_keys[2], 17, ""); // LoadLastState7 + set_control(m_keys[2], 18, ""); // LoadLastState8 + set_control(m_keys[2], 19, ""); // SaveFirstState + set_control(m_keys[2], 20, "`F12` & !(`Left Shift` | `Right Shift`)"); // UndoLoadState + set_control(m_keys[2], 21, "(`Left Shift` | `Right Shift`) & `F12`"); // UndoSaveState + set_control(m_keys[2], 22, ""); // SaveStateFile + set_control(m_keys[2], 23, ""); // LoadStateFile +#else // linux + set_control(m_keys[0], 0, "(Control_L | Control_R) & `O`"); // Open + set_control(m_keys[0], 1, ""); // ChangeDisc + set_control(m_keys[0], 2, ""); // RefreshList + set_control(m_keys[0], 3, "F10"); // PlayPause + set_control(m_keys[0], 4, "Escape"); // Stop + set_control(m_keys[0], 5, ""); // Reset + set_control(m_keys[0], 6, ""); // FrameAdvance + set_control(m_keys[0], 7, ""); // StartRecording + set_control(m_keys[0], 8, ""); // PlayRecording + set_control(m_keys[0], 9, ""); // ExportRecording + set_control(m_keys[0], 10, ""); // Readonlymode + set_control(m_keys[0], 11, "(Alt_L | Alt_R) & `Return`"); // ToggleFullscreen + set_control(m_keys[0], 12, "`F9` & !(Alt_L | Alt_R)"); // Screenshot + set_control(m_keys[0], 13, ""); // Exit + set_control(m_keys[0], 14, "(Alt_L | Alt_R) & `F5`"); // Wiimote1Connect + set_control(m_keys[0], 15, "(Alt_L | Alt_R) & `F6`"); // Wiimote2Connect + set_control(m_keys[0], 16, "(Alt_L | Alt_R) & `F7`"); // Wiimote3Connect + set_control(m_keys[0], 17, "(Alt_L | Alt_R) & `F8`"); // Wiimote4Connect + set_control(m_keys[0], 18, "(Alt_L | Alt_R) & `F9`"); // BalanceBoardConnect + set_control(m_keys[0], 19, ""); // VolumeDown + set_control(m_keys[0], 20, ""); // VolumeUp + set_control(m_keys[0], 21, ""); // VolumeToggleMute + set_control(m_keys[0], 22, ""); // ToggleIR + set_control(m_keys[0], 23, ""); // ToggleAspectRatio + set_control(m_keys[0], 24, ""); // ToggleEFBCopies + set_control(m_keys[0], 25, ""); // ToggleFog + set_control(m_keys[0], 26, "Tab"); // ToggleThrottle + set_control(m_keys[0], 27, ""); // DecreaseFrameLimit + set_control(m_keys[0], 28, ""); // IncreaseFrameLimit + set_control(m_keys[0], 29, "1"); // FreelookDecreaseSpeed + set_control(m_keys[0], 30, "2"); // FreelookIncreaseSpeed + set_control(m_keys[0], 31, "F"); // FreelookResetSpeed + set_control(m_keys[1], 0, "E"); // FreelookUp + set_control(m_keys[1], 1, "Q"); // FreelookDown + set_control(m_keys[1], 2, "A"); // FreelookLeft + set_control(m_keys[1], 3, "D"); // FreelookRight + set_control(m_keys[1], 4, "W"); // FreelookZoomIn + set_control(m_keys[1], 5, "S"); // FreelookZoomOut + set_control(m_keys[1], 6, "R"); // FreelookReset + set_control(m_keys[1], 7, ""); // DecreaseDepth + set_control(m_keys[1], 8, ""); // IncreaseDepth + set_control(m_keys[1], 9, ""); // DecreaseConvergence + set_control(m_keys[1], 10, ""); // IncreaseConvergence + set_control(m_keys[1], 11, "`F1` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot1 + set_control(m_keys[1], 12, "`F2` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot2 + set_control(m_keys[1], 13, "`F3` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot3 + set_control(m_keys[1], 14, "`F4` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot4 + set_control(m_keys[1], 15, "`F5` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot5 + set_control(m_keys[1], 16, "`F6` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot6 + set_control(m_keys[1], 17, "`F7` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot7 + set_control(m_keys[1], 18, "`F8` & !(Shift_L | Shift_R) & !(Alt_L | Alt_R)"); // LoadStateSlot8 + set_control(m_keys[1], 19, ""); // LoadStateSlot9 + set_control(m_keys[1], 20, ""); // LoadStateSlot10 + set_control(m_keys[1], 21, "(Shift_L | Shift_R) & `F1`"); // SaveStateSlot1 + set_control(m_keys[1], 22, "(Shift_L | Shift_R) & `F2`"); // SaveStateSlot2 + set_control(m_keys[1], 23, "(Shift_L | Shift_R) & `F3`"); // SaveStateSlot3 + set_control(m_keys[1], 24, "(Shift_L | Shift_R) & `F4`"); // SaveStateSlot4 + set_control(m_keys[1], 25, "(Shift_L | Shift_R) & `F5`"); // SaveStateSlot5 + set_control(m_keys[1], 26, "(Shift_L | Shift_R) & `F6`"); // SaveStateSlot6 + set_control(m_keys[1], 27, "(Shift_L | Shift_R) & `F7`"); // SaveStateSlot7 + set_control(m_keys[1], 28, "(Shift_L | Shift_R) & `F8`"); // SaveStateSlot8 + set_control(m_keys[1], 29, ""); // SaveStateSlot9 + set_control(m_keys[1], 30, ""); // SaveStateSlot10 + set_control(m_keys[1], 31, ""); // SelectStateSlot1 + set_control(m_keys[2], 0, ""); // SelectStateSlot2 + set_control(m_keys[2], 1, ""); // SelectStateSlot3 + set_control(m_keys[2], 2, ""); // SelectStateSlot4 + set_control(m_keys[2], 3, ""); // SelectStateSlot5 + set_control(m_keys[2], 4, ""); // SelectStateSlot6 + set_control(m_keys[2], 5, ""); // SelectStateSlot7 + set_control(m_keys[2], 6, ""); // SelectStateSlot8 + set_control(m_keys[2], 7, ""); // SelectStateSlot9 + set_control(m_keys[2], 8, ""); // SelectStateSlot10 + set_control(m_keys[2], 9, ""); // SaveSelectedSlot + set_control(m_keys[2], 10, ""); // LoadSelectedSlot + set_control(m_keys[2], 11, ""); // LoadLastState1 + set_control(m_keys[2], 12, ""); // LoadLastState2 + set_control(m_keys[2], 13, ""); // LoadLastState3 + set_control(m_keys[2], 14, ""); // LoadLastState4 + set_control(m_keys[2], 15, ""); // LoadLastState5 + set_control(m_keys[2], 16, ""); // LoadLastState6 + set_control(m_keys[2], 17, ""); // LoadLastState7 + set_control(m_keys[2], 18, ""); // LoadLastState8 + set_control(m_keys[2], 19, ""); // SaveFirstState + set_control(m_keys[2], 20, "`F12` & !(Shift_L | Shift_R)"); // UndoLoadState + set_control(m_keys[2], 21, "(Shift_L | Shift_R) & `F12`"); // UndoSaveState + set_control(m_keys[2], 22, ""); // SaveStateFile + set_control(m_keys[2], 23, ""); // LoadStateFile +#endif +} diff --git a/Source/Core/Core/HotkeyManager.h b/Source/Core/Core/HotkeyManager.h new file mode 100644 index 0000000000..159ba2dff6 --- /dev/null +++ b/Source/Core/Core/HotkeyManager.h @@ -0,0 +1,41 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "Core/CoreParameter.h" +#include "InputCommon/InputConfig.h" + +struct HotkeyStatus +{ + u32 button[6]; + s8 err; +}; + +class HotkeyManager : public ControllerEmu +{ +public: + HotkeyManager(); + ~HotkeyManager(); + + std::string GetName() const; + void GetInput(HotkeyStatus* const hk); + void LoadDefaults(const ControllerInterface& ciface); + +private: + Buttons* m_keys[6]; + ControlGroup* m_options; +}; + +namespace HotkeyManagerEmu +{ + void Initialize(void* const hwnd); + void Shutdown(); + + InputConfig* GetConfig(); + void GetStatus(u8 _port, HotkeyStatus* _pKeyboardStatus); + bool IsPressed(int Id, bool held); + + static u32 hotkeyDown[6]; +} diff --git a/Source/Core/DolphinWX/ConfigMain.cpp b/Source/Core/DolphinWX/ConfigMain.cpp index 3c2f775723..e421986381 100644 --- a/Source/Core/DolphinWX/ConfigMain.cpp +++ b/Source/Core/DolphinWX/ConfigMain.cpp @@ -32,6 +32,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "Core/HotkeyManager.h" #include "Core/Movie.h" #include "Core/NetPlayProto.h" #include "Core/HW/EXI.h" @@ -47,10 +48,13 @@ #include "DolphinWX/Frame.h" #include "DolphinWX/Globals.h" #include "DolphinWX/HotkeyDlg.h" +#include "DolphinWX/InputConfigDiag.h" #include "DolphinWX/Main.h" #include "DolphinWX/WxUtils.h" #include "DolphinWX/Debugger/CodeWindow.h" +#include "InputCommon/InputConfig.h" + #include "VideoCommon/VideoBackendBase.h" #define TEXT_BOX(page, text) new wxStaticText(page, wxID_ANY, text) @@ -919,8 +923,34 @@ void CConfigMain::DisplaySettingsChanged(wxCommandEvent& event) break; case ID_HOTKEY_CONFIG: { - HotkeyConfigDialog m_HotkeyDialog(this); - m_HotkeyDialog.ShowModal(); + bool was_init = false; + + InputConfig* const hotkey_plugin = HotkeyManagerEmu::GetConfig(); + + // check if game is running + if (g_controller_interface.IsInit()) + { + was_init = true; + } + else + { +#if defined(HAVE_X11) && HAVE_X11 + Window win = X11Utils::XWindowFromHandle(GetHandle()); + HotkeyManagerEmu::Initialize(reinterpret_cast(win)); +#else + HotkeyManagerEmu::Initialize(reinterpret_cast(GetHandle())); +#endif + } + + InputConfigDialog m_ConfigFrame(this, *hotkey_plugin, _("Dolphin Hotkeys"), 0); + m_ConfigFrame.ShowModal(); + m_ConfigFrame.Destroy(); + + // if game isn't running + if (!was_init) + { + HotkeyManagerEmu::Shutdown(); + } } // Update the GUI in case menu accelerators were changed main_frame->UpdateGUI(); diff --git a/Source/Core/DolphinWX/Frame.cpp b/Source/Core/DolphinWX/Frame.cpp index f181c793af..83ad8f8afc 100644 --- a/Source/Core/DolphinWX/Frame.cpp +++ b/Source/Core/DolphinWX/Frame.cpp @@ -46,6 +46,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/CoreParameter.h" +#include "Core/HotkeyManager.h" #include "Core/Movie.h" #include "Core/State.h" #include "Core/HW/DVDInterface.h" @@ -269,6 +270,7 @@ EVT_MENU(IDM_CONFIG_GFX_BACKEND, CFrame::OnConfigGFX) EVT_MENU(IDM_CONFIG_AUDIO, CFrame::OnConfigAudio) EVT_MENU(IDM_CONFIG_CONTROLLERS, CFrame::OnConfigControllers) EVT_MENU(IDM_CONFIG_HOTKEYS, CFrame::OnConfigHotkey) +EVT_MENU(IDM_CONFIG_MENU_COMMANDS, CFrame::OnConfigMenuCommands) EVT_MENU(IDM_SAVE_PERSPECTIVE, CFrame::OnPerspectiveMenu) EVT_MENU(IDM_EDIT_PERSPECTIVES, CFrame::OnPerspectiveMenu) @@ -342,6 +344,22 @@ END_EVENT_TABLE() // --------------- // Creation and close, quit functions + +bool CFrame::InitHotkeys() +{ + if (!g_controller_interface.IsInit()) + { +#if defined(HAVE_X11) && HAVE_X11 + Window win = X11Utils::XWindowFromHandle(GetHandle()); + HotkeyManagerEmu::Initialize(reinterpret_cast(win)); +#else + HotkeyManagerEmu::Initialize(reinterpret_cast(GetHandle())); +#endif + return true; + } + return false; +} + CFrame::CFrame(wxFrame* parent, wxWindowID id, const wxString& title, @@ -477,10 +495,24 @@ CFrame::CFrame(wxFrame* parent, UpdateGUI(); if (g_pCodeWindow) g_pCodeWindow->UpdateButtonStates(); + + // check if game is running + m_bHotkeysInit = InitHotkeys(); + + m_poll_hotkey_timer = new wxTimer(this); + Bind(wxEVT_TIMER, &CFrame::PollHotkeys, this); + m_poll_hotkey_timer->Start(1000 / 60, wxTIMER_CONTINUOUS); } // Destructor CFrame::~CFrame() { + m_poll_hotkey_timer->Stop(); + + if (m_bHotkeysInit) + { + HotkeyManagerEmu::Shutdown(); + } + drives.clear(); #if defined(HAVE_XRANDR) && HAVE_XRANDR @@ -904,11 +936,15 @@ void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event)) } } -static bool IsHotkey(wxKeyEvent &event, int Id) +static bool IsHotkey(wxKeyEvent &event, int Id, bool keyUp = false) { - return (event.GetKeyCode() != WXK_NONE && - event.GetKeyCode() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkey[Id] && - event.GetModifiers() == SConfig::GetInstance().m_LocalCoreStartupParameter.iHotkeyModifier[Id]); + // Input event hotkey + if (event.GetKeyCode() == WXK_NONE) + { + return HotkeyManagerEmu::IsPressed(Id, keyUp); + } + + return false; } int GetCmdForHotkey(unsigned int key) @@ -1045,202 +1081,12 @@ bool TASInputHasFocus() return false; } - void CFrame::OnKeyDown(wxKeyEvent& event) { if (Core::GetState() != Core::CORE_UNINITIALIZED && (RendererHasFocus() || TASInputHasFocus())) { - int WiimoteId = -1; - // Toggle fullscreen - if (IsHotkey(event, HK_FULLSCREEN)) - DoFullscreen(!RendererIsFullscreen()); - // Send Debugger keys to CodeWindow - else if (g_pCodeWindow && (event.GetKeyCode() >= WXK_F9 && event.GetKeyCode() <= WXK_F11)) - event.Skip(); - // Pause and Unpause - else if (IsHotkey(event, HK_PLAY_PAUSE)) - DoPause(); - // Stop - else if (IsHotkey(event, HK_STOP)) - DoStop(); - // Screenshot hotkey - else if (IsHotkey(event, HK_SCREENSHOT)) - Core::SaveScreenShot(); - else if (IsHotkey(event, HK_EXIT)) - wxPostEvent(this, wxCommandEvent(wxID_EXIT)); - else if (IsHotkey(event, HK_VOLUME_DOWN)) - AudioCommon::DecreaseVolume(3); - else if (IsHotkey(event, HK_VOLUME_UP)) - AudioCommon::IncreaseVolume(3); - else if (IsHotkey(event, HK_VOLUME_TOGGLE_MUTE)) - AudioCommon::ToggleMuteVolume(); - // Wiimote connect and disconnect hotkeys - else if (IsHotkey(event, HK_WIIMOTE1_CONNECT)) - WiimoteId = 0; - else if (IsHotkey(event, HK_WIIMOTE2_CONNECT)) - WiimoteId = 1; - else if (IsHotkey(event, HK_WIIMOTE3_CONNECT)) - WiimoteId = 2; - else if (IsHotkey(event, HK_WIIMOTE4_CONNECT)) - WiimoteId = 3; - else if (IsHotkey(event, HK_BALANCEBOARD_CONNECT)) - WiimoteId = 4; - else if (IsHotkey(event, HK_TOGGLE_IR)) - { - OSDChoice = 1; - // Toggle native resolution - if (++g_Config.iEFBScale > SCALE_4X) - g_Config.iEFBScale = SCALE_AUTO; - } - else if (IsHotkey(event, HK_TOGGLE_AR)) - { - OSDChoice = 2; - // Toggle aspect ratio - g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3; - } - else if (IsHotkey(event, HK_TOGGLE_EFBCOPIES)) - { - OSDChoice = 3; - // Toggle EFB copies between EFB2RAM and EFB2Texture - if (!g_Config.bEFBCopyEnable) - { - OSD::AddMessage("EFB Copies are disabled, enable them in Graphics settings for toggling", 6000); - } - else - { - g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture; - } - } - else if (IsHotkey(event, HK_TOGGLE_FOG)) - { - OSDChoice = 4; - g_Config.bDisableFog = !g_Config.bDisableFog; - } - else if (IsHotkey(event, HK_TOGGLE_THROTTLE)) - { - Core::SetIsFramelimiterTempDisabled(true); - } - else if (IsHotkey(event, HK_DECREASE_FRAME_LIMIT)) - { - if (--SConfig::GetInstance().m_Framelimit > 0x19) - SConfig::GetInstance().m_Framelimit = 0x19; - } - else if (IsHotkey(event, HK_INCREASE_FRAME_LIMIT)) - { - if (++SConfig::GetInstance().m_Framelimit > 0x19) - SConfig::GetInstance().m_Framelimit = 0; - } - else if (IsHotkey(event, HK_SAVE_STATE_SLOT_SELECTED)) - { - State::Save(g_saveSlot); - } - else if (IsHotkey(event, HK_LOAD_STATE_SLOT_SELECTED)) - { - State::Load(g_saveSlot); - } - else if (IsHotkey(event, HK_DECREASE_DEPTH)) - { - if (--g_Config.iStereoDepth < 0) - g_Config.iStereoDepth = 0; - } - else if (IsHotkey(event, HK_INCREASE_DEPTH)) - { - if (++g_Config.iStereoDepth > 100) - g_Config.iStereoDepth = 100; - } - else if (IsHotkey(event, HK_DECREASE_CONVERGENCE)) - { - if (--g_Config.iStereoConvergence < 0) - g_Config.iStereoConvergence = 0; - } - else if (IsHotkey(event, HK_INCREASE_CONVERGENCE)) - { - if (++g_Config.iStereoConvergence > 500) - g_Config.iStereoConvergence = 500; - } - - else - { - for (int i = HK_SELECT_STATE_SLOT_1; i < HK_SELECT_STATE_SLOT_10; ++i) - { - if (IsHotkey (event, i)) - { - wxCommandEvent slot_event; - slot_event.SetId(i + IDM_SELECT_SLOT_1 - HK_SELECT_STATE_SLOT_1); - CFrame::OnSelectSlot(slot_event); - } - } - - unsigned int i = NUM_HOTKEYS; - if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain || TASInputHasFocus()) - { - for (i = 0; i < NUM_HOTKEYS; i++) - { - if (IsHotkey(event, i)) - { - int cmd = GetCmdForHotkey(i); - if (cmd >= 0) - { - wxCommandEvent evt(wxEVT_MENU, cmd); - wxMenuItem *item = GetMenuBar()->FindItem(cmd); - if (item && item->IsCheckable()) - { - item->wxMenuItemBase::Toggle(); - evt.SetInt(item->IsChecked()); - } - GetEventHandler()->AddPendingEvent(evt); - break; - } - } - } - } - // On OS X, we claim all keyboard events while - // emulation is running to avoid wxWidgets sounding - // the system beep for unhandled key events when - // receiving pad/Wiimote keypresses which take an - // entirely different path through the HID subsystem. -#ifndef __APPLE__ - // On other platforms, we leave the key event alone - // so it can be passed on to the windowing system. - if (i == NUM_HOTKEYS) - event.Skip(); -#endif - } - - // Actually perform the Wiimote connection or disconnection - if (WiimoteId >= 0) - { - wxCommandEvent evt; - evt.SetId(IDM_CONNECT_WIIMOTE1 + WiimoteId); - OnConnectWiimote(evt); - } - - if (g_Config.bFreeLook) - { - static float debugSpeed = 1.0f; - - if (IsHotkey(event, HK_FREELOOK_DECREASE_SPEED)) - debugSpeed /= 2.0f; - else if (IsHotkey(event, HK_FREELOOK_INCREASE_SPEED)) - debugSpeed *= 2.0f; - else if (IsHotkey(event, HK_FREELOOK_RESET_SPEED)) - debugSpeed = 1.0f; - else if (IsHotkey(event, HK_FREELOOK_UP)) - VertexShaderManager::TranslateView(0.0f, 0.0f, -debugSpeed); - else if (IsHotkey(event, HK_FREELOOK_DOWN)) - VertexShaderManager::TranslateView(0.0f, 0.0f, debugSpeed); - else if (IsHotkey(event, HK_FREELOOK_LEFT)) - VertexShaderManager::TranslateView(debugSpeed, 0.0f); - else if (IsHotkey(event, HK_FREELOOK_RIGHT)) - VertexShaderManager::TranslateView(-debugSpeed, 0.0f); - else if (IsHotkey(event, HK_FREELOOK_ZOOM_IN)) - VertexShaderManager::TranslateView(0.0f, debugSpeed); - else if (IsHotkey(event, HK_FREELOOK_ZOOM_OUT)) - VertexShaderManager::TranslateView(0.0f, -debugSpeed); - else if (IsHotkey(event, HK_FREELOOK_RESET)) - VertexShaderManager::ResetView(); - } + ParseHotkeys(event); } else { @@ -1410,3 +1256,223 @@ const CGameListCtrl *CFrame::GetGameListCtrl() const { return m_GameListCtrl; } + +void CFrame::PollHotkeys(wxTimerEvent& event) +{ + if (Core::GetState() == Core::CORE_UNINITIALIZED || Core::GetState() == Core::CORE_PAUSE) + { + InitHotkeys(); + g_controller_interface.UpdateInput(); + } + + if (Core::GetState() != Core::CORE_STOPPING) + { + wxKeyEvent keyevent = 0; + + if (IsHotkey(keyevent, HK_TOGGLE_THROTTLE)) + { + Core::SetIsFramelimiterTempDisabled(false); + } + else + { + ParseHotkeys(keyevent); + } + } +} + +void CFrame::ParseHotkeys(wxKeyEvent &event) +{ + int WiimoteId = -1; + // Toggle fullscreen + if (IsHotkey(event, HK_FULLSCREEN)) + DoFullscreen(!RendererIsFullscreen()); + // Send Debugger keys to CodeWindow + else if (g_pCodeWindow && (event.GetKeyCode() >= WXK_F9 && event.GetKeyCode() <= WXK_F11)) + event.Skip(); + // Pause and Unpause + else if (IsHotkey(event, HK_PLAY_PAUSE)) + DoPause(); + // Stop + else if (IsHotkey(event, HK_STOP)) + DoStop(); + // Screenshot hotkey + else if (IsHotkey(event, HK_SCREENSHOT)) + Core::SaveScreenShot(); + else if (IsHotkey(event, HK_EXIT)) + wxPostEvent(this, wxCommandEvent(wxID_EXIT)); + else if (IsHotkey(event, HK_VOLUME_DOWN)) + AudioCommon::DecreaseVolume(3); + else if (IsHotkey(event, HK_VOLUME_UP)) + AudioCommon::IncreaseVolume(3); + else if (IsHotkey(event, HK_VOLUME_TOGGLE_MUTE)) + AudioCommon::ToggleMuteVolume(); + // Wiimote connect and disconnect hotkeys + else if (IsHotkey(event, HK_WIIMOTE1_CONNECT)) + WiimoteId = 0; + else if (IsHotkey(event, HK_WIIMOTE2_CONNECT)) + WiimoteId = 1; + else if (IsHotkey(event, HK_WIIMOTE3_CONNECT)) + WiimoteId = 2; + else if (IsHotkey(event, HK_WIIMOTE4_CONNECT)) + WiimoteId = 3; + else if (IsHotkey(event, HK_BALANCEBOARD_CONNECT)) + WiimoteId = 4; + else if (IsHotkey(event, HK_TOGGLE_IR)) + { + OSDChoice = 1; + // Toggle native resolution + if (++g_Config.iEFBScale > SCALE_4X) + g_Config.iEFBScale = SCALE_AUTO; + } + else if (IsHotkey(event, HK_TOGGLE_AR)) + { + OSDChoice = 2; + // Toggle aspect ratio + g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3; + } + else if (IsHotkey(event, HK_TOGGLE_EFBCOPIES)) + { + OSDChoice = 3; + // Toggle EFB copies between EFB2RAM and EFB2Texture + if (!g_Config.bEFBCopyEnable) + { + OSD::AddMessage("EFB Copies are disabled, enable them in Graphics settings for toggling", 6000); + } + else + { + g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture; + } + } + else if (IsHotkey(event, HK_TOGGLE_FOG)) + { + OSDChoice = 4; + g_Config.bDisableFog = !g_Config.bDisableFog; + } + else if (IsHotkey(event, HK_TOGGLE_THROTTLE, true)) + { + Core::SetIsFramelimiterTempDisabled(true); + } + else if (IsHotkey(event, HK_DECREASE_FRAME_LIMIT)) + { + if (--SConfig::GetInstance().m_Framelimit > 0x19) + SConfig::GetInstance().m_Framelimit = 0x19; + } + else if (IsHotkey(event, HK_INCREASE_FRAME_LIMIT)) + { + if (++SConfig::GetInstance().m_Framelimit > 0x19) + SConfig::GetInstance().m_Framelimit = 0; + } + else if (IsHotkey(event, HK_SAVE_STATE_SLOT_SELECTED)) + { + State::Save(g_saveSlot); + } + else if (IsHotkey(event, HK_LOAD_STATE_SLOT_SELECTED)) + { + State::Load(g_saveSlot); + } + else if (IsHotkey(event, HK_DECREASE_DEPTH)) + { + if (--g_Config.iStereoDepth < 0) + g_Config.iStereoDepth = 0; + } + else if (IsHotkey(event, HK_INCREASE_DEPTH)) + { + if (++g_Config.iStereoDepth > 100) + g_Config.iStereoDepth = 100; + } + else if (IsHotkey(event, HK_DECREASE_CONVERGENCE)) + { + if (--g_Config.iStereoConvergence < 0) + g_Config.iStereoConvergence = 0; + } + else if (IsHotkey(event, HK_INCREASE_CONVERGENCE)) + { + if (++g_Config.iStereoConvergence > 500) + g_Config.iStereoConvergence = 500; + } + + else + { + for (int i = HK_SELECT_STATE_SLOT_1; i < HK_SELECT_STATE_SLOT_10; ++i) + { + if (IsHotkey(event, i)) + { + wxCommandEvent slot_event; + slot_event.SetId(i + IDM_SELECT_SLOT_1 - HK_SELECT_STATE_SLOT_1); + CFrame::OnSelectSlot(slot_event); + } + } + + unsigned int i = NUM_HOTKEYS; + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bRenderToMain || TASInputHasFocus()) + { + for (i = 0; i < NUM_HOTKEYS; i++) + { + if (IsHotkey(event, i)) + { + int cmd = GetCmdForHotkey(i); + if (cmd >= 0) + { + wxCommandEvent evt(wxEVT_MENU, cmd); + wxMenuItem *item = GetMenuBar()->FindItem(cmd); + if (item && item->IsCheckable()) + { + item->wxMenuItemBase::Toggle(); + evt.SetInt(item->IsChecked()); + } + GetEventHandler()->AddPendingEvent(evt); + break; + } + } + } + } + // On OS X, we claim all keyboard events while + // emulation is running to avoid wxWidgets sounding + // the system beep for unhandled key events when + // receiving pad/Wiimote keypresses which take an + // entirely different path through the HID subsystem. +#ifndef __APPLE__ + // On other platforms, we leave the key event alone + // so it can be passed on to the windowing system. + if (i == NUM_HOTKEYS) + event.Skip(); +#endif + } + + // Actually perform the Wiimote connection or disconnection + if (Core::GetState() != Core::CORE_UNINITIALIZED) + { + if (WiimoteId >= 0) + { + wxCommandEvent evt; + evt.SetId(IDM_CONNECT_WIIMOTE1 + WiimoteId); + OnConnectWiimote(evt); + } + + if (g_Config.bFreeLook) + { + static float debugSpeed = 1.0f; + + if (IsHotkey(event, HK_FREELOOK_DECREASE_SPEED)) + debugSpeed /= 2.0f; + else if (IsHotkey(event, HK_FREELOOK_INCREASE_SPEED)) + debugSpeed *= 2.0f; + else if (IsHotkey(event, HK_FREELOOK_RESET_SPEED)) + debugSpeed = 1.0f; + else if (IsHotkey(event, HK_FREELOOK_UP)) + VertexShaderManager::TranslateView(0.0f, 0.0f, -debugSpeed); + else if (IsHotkey(event, HK_FREELOOK_DOWN)) + VertexShaderManager::TranslateView(0.0f, 0.0f, debugSpeed); + else if (IsHotkey(event, HK_FREELOOK_LEFT)) + VertexShaderManager::TranslateView(debugSpeed, 0.0f); + else if (IsHotkey(event, HK_FREELOOK_RIGHT)) + VertexShaderManager::TranslateView(-debugSpeed, 0.0f); + else if (IsHotkey(event, HK_FREELOOK_ZOOM_IN)) + VertexShaderManager::TranslateView(0.0f, debugSpeed); + else if (IsHotkey(event, HK_FREELOOK_ZOOM_OUT)) + VertexShaderManager::TranslateView(0.0f, -debugSpeed); + else if (IsHotkey(event, HK_FREELOOK_RESET)) + VertexShaderManager::ResetView(); + } + } +} diff --git a/Source/Core/DolphinWX/Frame.h b/Source/Core/DolphinWX/Frame.h index d7c1537f1c..a636f843d2 100644 --- a/Source/Core/DolphinWX/Frame.h +++ b/Source/Core/DolphinWX/Frame.h @@ -47,6 +47,8 @@ class wxAuiNotebook; class wxAuiNotebookEvent; class wxListEvent; class wxMenuItem; +class wxTimer; +class wxTimerEvent; class wxWindow; class CRenderFrame : public wxFrame @@ -175,6 +177,7 @@ private: bool m_bGameLoading; bool m_bClosing; bool m_confirmStop; + bool m_bHotkeysInit; std::vector drives; @@ -195,6 +198,8 @@ private: EToolbar_Max }; + wxTimer* m_poll_hotkey_timer; + wxBitmap m_Bitmaps[EToolbar_Max]; wxBitmap m_BitmapsMenu[EToolbar_Max]; @@ -295,6 +300,7 @@ private: void OnConfigAudio(wxCommandEvent& event); void OnConfigControllers(wxCommandEvent& event); void OnConfigHotkey(wxCommandEvent& event); + void OnConfigMenuCommands(wxCommandEvent& event); void OnToggleFullscreen(wxCommandEvent& event); void OnToggleDualCore(wxCommandEvent& event); @@ -337,6 +343,11 @@ private: void OnSaveCurrentSlot(wxCommandEvent& event); void OnLoadCurrentSlot(wxCommandEvent& event); + void PollHotkeys(wxTimerEvent&); + void ParseHotkeys(wxKeyEvent &event); + + bool InitHotkeys(); + // Event table DECLARE_EVENT_TABLE(); }; diff --git a/Source/Core/DolphinWX/FrameTools.cpp b/Source/Core/DolphinWX/FrameTools.cpp index 08ddcb2e39..fd8f7ae8d4 100644 --- a/Source/Core/DolphinWX/FrameTools.cpp +++ b/Source/Core/DolphinWX/FrameTools.cpp @@ -46,6 +46,7 @@ #include "Core/Core.h" #include "Core/CoreParameter.h" #include "Core/Host.h" +#include "Core/HotkeyManager.h" #include "Core/Movie.h" #include "Core/State.h" #include "Core/HW/CPU.h" @@ -238,6 +239,7 @@ wxMenuBar* CFrame::CreateMenu() pOptionsMenu->Append(IDM_CONFIG_AUDIO, _("&Audio Settings")); pOptionsMenu->Append(IDM_CONFIG_CONTROLLERS, _("&Controller Settings")); pOptionsMenu->Append(IDM_CONFIG_HOTKEYS, _("&Hotkey Settings")); + pOptionsMenu->Append(IDM_CONFIG_MENU_COMMANDS, _("&Menu Accelerators")); if (g_pCodeWindow) { pOptionsMenu->AppendSeparator(); @@ -1350,11 +1352,48 @@ void CFrame::OnConfigControllers(wxCommandEvent& WXUNUSED (event)) config_dlg.Destroy(); } -void CFrame::OnConfigHotkey(wxCommandEvent& WXUNUSED (event)) +void CFrame::OnConfigMenuCommands(wxCommandEvent& WXUNUSED(event)) { HotkeyConfigDialog *m_HotkeyDialog = new HotkeyConfigDialog(this); m_HotkeyDialog->ShowModal(); m_HotkeyDialog->Destroy(); + + // Update the GUI in case menu accelerators were changed + UpdateGUI(); +} + + +void CFrame::OnConfigHotkey(wxCommandEvent& WXUNUSED (event)) +{ + bool was_init = false; + + InputConfig* const hotkey_plugin = HotkeyManagerEmu::GetConfig(); + + // check if game is running + if (g_controller_interface.IsInit()) + { + was_init = true; + } + else + { +#if defined(HAVE_X11) && HAVE_X11 + Window win = X11Utils::XWindowFromHandle(GetHandle()); + HotkeyManagerEmu::Initialize(reinterpret_cast(win)); +#else + HotkeyManagerEmu::Initialize(reinterpret_cast(GetHandle())); +#endif + } + + InputConfigDialog m_ConfigFrame(this, *hotkey_plugin, _("Dolphin Hotkeys"), 0); + m_ConfigFrame.ShowModal(); + m_ConfigFrame.Destroy(); + + // if game isn't running + if (!was_init) + { + HotkeyManagerEmu::Shutdown(); + } + // Update the GUI in case menu accelerators were changed UpdateGUI(); } diff --git a/Source/Core/DolphinWX/Globals.h b/Source/Core/DolphinWX/Globals.h index fe888d222d..2ca8a01f6d 100644 --- a/Source/Core/DolphinWX/Globals.h +++ b/Source/Core/DolphinWX/Globals.h @@ -149,6 +149,7 @@ enum IDM_CONFIG_AUDIO, IDM_CONFIG_CONTROLLERS, IDM_CONFIG_HOTKEYS, + IDM_CONFIG_MENU_COMMANDS, IDM_CONFIG_LOGGER, // Views diff --git a/Source/Core/DolphinWX/HotkeyDlg.cpp b/Source/Core/DolphinWX/HotkeyDlg.cpp index 39746df698..8eb51c430c 100644 --- a/Source/Core/DolphinWX/HotkeyDlg.cpp +++ b/Source/Core/DolphinWX/HotkeyDlg.cpp @@ -185,6 +185,112 @@ void HotkeyConfigDialog::OnButtonClick(wxCommandEvent& event) #define HOTKEY_NUM_COLUMNS 2 +const wxString hkText[] = +{ + _("Open"), + _("Change Disc"), + _("Refresh List"), + + _("Play/Pause"), + _("Stop"), + _("Reset"), + _("Frame Advance"), + + _("Start Recording"), + _("Play Recording"), + _("Export Recording"), + _("Read-only mode"), + + _("Toggle Fullscreen"), + _("Take Screenshot"), + _("Exit"), + + _("Connect Wiimote 1"), + _("Connect Wiimote 2"), + _("Connect Wiimote 3"), + _("Connect Wiimote 4"), + _("Connect Balance Board"), + + _("Volume Down"), + _("Volume Up"), + _("Volume Toggle Mute"), + + _("Toggle IR"), + _("Toggle Aspect Ratio"), + _("Toggle EFB Copies"), + _("Toggle Fog"), + _("Toggle Frame limit"), + _("Decrease Frame limit"), + _("Increase Frame limit"), + + _("Freelook Decrease Speed"), + _("Freelook Increase Speed"), + _("Freelook Reset Speed"), + _("Freelook Move Up"), + _("Freelook Move Down"), + _("Freelook Move Left"), + _("Freelook Move Right"), + _("Freelook Zoom In"), + _("Freelook Zoom Out"), + _("Freelook Reset"), + + _("Decrease Depth"), + _("Increase Depth"), + _("Decrease Convergence"), + _("Increase Convergence"), + + _("Load State Slot 1"), + _("Load State Slot 2"), + _("Load State Slot 3"), + _("Load State Slot 4"), + _("Load State Slot 5"), + _("Load State Slot 6"), + _("Load State Slot 7"), + _("Load State Slot 8"), + _("Load State Slot 9"), + _("Load State Slot 10"), + + _("Save State Slot 1"), + _("Save State Slot 2"), + _("Save State Slot 3"), + _("Save State Slot 4"), + _("Save State Slot 5"), + _("Save State Slot 6"), + _("Save State Slot 7"), + _("Save State Slot 8"), + _("Save State Slot 9"), + _("Save State Slot 10"), + + _("Select State Slot 1"), + _("Select State Slot 2"), + _("Select State Slot 3"), + _("Select State Slot 4"), + _("Select State Slot 5"), + _("Select State Slot 6"), + _("Select State Slot 7"), + _("Select State Slot 8"), + _("Select State Slot 9"), + _("Select State Slot 10"), + + _("Save to selected slot"), + _("Load from selected slot"), + + _("Load State Last 1"), + _("Load State Last 2"), + _("Load State Last 3"), + _("Load State Last 4"), + _("Load State Last 5"), + _("Load State Last 6"), + _("Load State Last 7"), + _("Load State Last 8"), + + _("Save Oldest State"), + _("Undo Load State"), + _("Undo Save State"), + _("Save State"), + _("Load State"), +}; + void HotkeyConfigDialog::CreateHotkeyGUIControls() { const wxString pageNames[] = @@ -193,112 +299,6 @@ void HotkeyConfigDialog::CreateHotkeyGUIControls() _("State Saves") }; - const wxString hkText[] = - { - _("Open"), - _("Change Disc"), - _("Refresh List"), - - _("Play/Pause"), - _("Stop"), - _("Reset"), - _("Frame Advance"), - - _("Start Recording"), - _("Play Recording"), - _("Export Recording"), - _("Read-only mode"), - - _("Toggle Fullscreen"), - _("Take Screenshot"), - _("Exit"), - - _("Connect Wiimote 1"), - _("Connect Wiimote 2"), - _("Connect Wiimote 3"), - _("Connect Wiimote 4"), - _("Connect Balance Board"), - - _("Volume Down"), - _("Volume Up"), - _("Volume Toggle Mute"), - - _("Toggle IR"), - _("Toggle Aspect Ratio"), - _("Toggle EFB Copies"), - _("Toggle Fog"), - _("Toggle Frame limit"), - _("Decrease Frame limit"), - _("Increase Frame limit"), - - _("Freelook Decrease Speed"), - _("Freelook Increase Speed"), - _("Freelook Reset Speed"), - _("Freelook Move Up"), - _("Freelook Move Down"), - _("Freelook Move Left"), - _("Freelook Move Right"), - _("Freelook Zoom In"), - _("Freelook Zoom Out"), - _("Freelook Reset"), - - _("Decrease Depth"), - _("Increase Depth"), - _("Decrease Convergence"), - _("Increase Convergence"), - - _("Load State Slot 1"), - _("Load State Slot 2"), - _("Load State Slot 3"), - _("Load State Slot 4"), - _("Load State Slot 5"), - _("Load State Slot 6"), - _("Load State Slot 7"), - _("Load State Slot 8"), - _("Load State Slot 9"), - _("Load State Slot 10"), - - _("Save State Slot 1"), - _("Save State Slot 2"), - _("Save State Slot 3"), - _("Save State Slot 4"), - _("Save State Slot 5"), - _("Save State Slot 6"), - _("Save State Slot 7"), - _("Save State Slot 8"), - _("Save State Slot 9"), - _("Save State Slot 10"), - - _("Select State Slot 1"), - _("Select State Slot 2"), - _("Select State Slot 3"), - _("Select State Slot 4"), - _("Select State Slot 5"), - _("Select State Slot 6"), - _("Select State Slot 7"), - _("Select State Slot 8"), - _("Select State Slot 9"), - _("Select State Slot 10"), - - _("Save to selected slot"), - _("Load from selected slot"), - - _("Load State Last 1"), - _("Load State Last 2"), - _("Load State Last 3"), - _("Load State Last 4"), - _("Load State Last 5"), - _("Load State Last 6"), - _("Load State Last 7"), - _("Load State Last 8"), - - _("Save Oldest State"), - _("Undo Load State"), - _("Undo Save State"), - _("Save State"), - _("Load State"), - }; - const int page_breaks[3] = {HK_OPEN, HK_LOAD_STATE_SLOT_1, NUM_HOTKEYS}; // Configuration controls sizes diff --git a/Source/Core/DolphinWX/HotkeyDlg.h b/Source/Core/DolphinWX/HotkeyDlg.h index 71d863a1aa..db4c687c52 100644 --- a/Source/Core/DolphinWX/HotkeyDlg.h +++ b/Source/Core/DolphinWX/HotkeyDlg.h @@ -29,7 +29,7 @@ class HotkeyConfigDialog : public wxDialog public: HotkeyConfigDialog(wxWindow* parent, wxWindowID id = wxID_ANY, - const wxString &title = _("Hotkey Configuration"), + const wxString &title = _("Menu Accelerators"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE); diff --git a/Source/Core/DolphinWX/InputConfigDiag.cpp b/Source/Core/DolphinWX/InputConfigDiag.cpp index 5073a932f4..df728d5f3c 100644 --- a/Source/Core/DolphinWX/InputConfigDiag.cpp +++ b/Source/Core/DolphinWX/InputConfigDiag.cpp @@ -839,7 +839,7 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin // Draw buttons in rows of 8 unsigned int button_cols = group->controls.size() > 8 ? 8 : group->controls.size(); unsigned int button_rows = ceil((float)group->controls.size() / 8.0f); - wxBitmap bitmap(int(12 * button_cols + 1), (12 * button_rows) - (button_rows - 1)); + wxBitmap bitmap(int(12 * button_cols + 1), (11 * button_rows) + 1); dc.SelectObject(bitmap); dc.Clear(); @@ -1074,6 +1074,7 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputConfig& config szr->Add(m_pad_notebook, 0, wxEXPAND|wxTOP|wxLEFT|wxRIGHT, 5); szr->Add(CreateButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT), 0, wxEXPAND|wxALL, 5); + SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED); SetSizerAndFit(szr); Center(); diff --git a/Source/Core/DolphinWX/InputConfigDiagBitmaps.cpp b/Source/Core/DolphinWX/InputConfigDiagBitmaps.cpp index 27340d2864..a78c7b013c 100644 --- a/Source/Core/DolphinWX/InputConfigDiagBitmaps.cpp +++ b/Source/Core/DolphinWX/InputConfigDiagBitmaps.cpp @@ -119,12 +119,12 @@ void DrawButton(unsigned int* const bitmasks, unsigned int buttons, unsigned int unsigned char amt = 255 - g->control_group->controls[(row * 8) + n]->control_ref->State() * 128; dc.SetBrush(wxBrush(wxColour(amt, amt, amt))); } - dc.DrawRectangle(n * 12, (row == 0) ? 0 : (row * 12 - 1), 14, 12); + dc.DrawRectangle(n * 12, (row == 0) ? 0 : (row * 11), 14, 12); // text const std::string name = g->control_group->controls[(row * 8) + n]->name; // bit of hax so ZL, ZR show up as L, R - dc.DrawText(StrToWxStr(std::string(1, (name[1] && name[1] < 'a') ? name[1] : name[0])), n * 12 + 2, 1 + ((row == 0) ? 0 : (row * 12 - 1))); + dc.DrawText(StrToWxStr(std::string(1, (name[1] && name[1] < 'a') ? name[1] : name[0])), n * 12 + 2, 1 + ((row == 0) ? 0 : (row * 11))); } static void DrawControlGroupBox(wxDC &dc, ControlGroupBox *g)