123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632 |
- /*
- * InputHandler.cpp
- * ----------------
- * Purpose: Implementation of keyboard input handling, keymap loading, ...
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #include "stdafx.h"
- #include "CommandSet.h"
- #include "InputHandler.h"
- #include "resource.h"
- #include "Mainfrm.h"
- #include "../soundlib/MIDIEvents.h"
- OPENMPT_NAMESPACE_BEGIN
- #define TRANSITIONBIT 0x8000
- #define REPEATBIT 0x4000
- CInputHandler::CInputHandler(CWnd *mainframe)
- {
- m_pMainFrm = mainframe;
- //Init CommandSet and Load defaults
- m_activeCommandSet = std::make_unique<CCommandSet>();
- m_lastCommands.fill(kcNull);
- mpt::PathString sDefaultPath = theApp.GetConfigPath() + P_("Keybindings.mkb");
- const bool bNoExistingKbdFileSetting = TrackerSettings::Instance().m_szKbdFile.empty();
- // 1. Try to load keybindings from the path saved in the settings.
- // 2. If the setting doesn't exist or the loading fails, try to load from default location.
- // 3. If neither one of these worked, load default keybindings from resources.
- // 4. If there were no keybinding setting already, create a keybinding file to default location
- // and set its path to settings.
- if (bNoExistingKbdFileSetting || !(m_activeCommandSet->LoadFile(TrackerSettings::Instance().m_szKbdFile)))
- {
- if (bNoExistingKbdFileSetting)
- TrackerSettings::Instance().m_szKbdFile = sDefaultPath;
- bool bSuccess = false;
- if (sDefaultPath.IsFile())
- bSuccess = m_activeCommandSet->LoadFile(sDefaultPath);
- if (!bSuccess)
- {
- // Load keybindings from resources.
- MPT_LOG_GLOBAL(LogDebug, "InputHandler", U_("Loading keybindings from resources\n"));
- bSuccess = m_activeCommandSet->LoadDefaultKeymap();
- if (bSuccess && bNoExistingKbdFileSetting)
- {
- m_activeCommandSet->SaveFile(TrackerSettings::Instance().m_szKbdFile);
- }
- }
- if (!bSuccess)
- ErrorBox(IDS_UNABLE_TO_LOAD_KEYBINDINGS);
- }
- // We will only overwrite the default Keybindings.mkb file from now on.
- TrackerSettings::Instance().m_szKbdFile = sDefaultPath;
- //Get Keymap
- m_activeCommandSet->GenKeyMap(m_keyMap);
- SetupSpecialKeyInterception(); // Feature: use Windows keys as modifier keys, intercept special keys
- }
- CommandID CInputHandler::SendCommands(CWnd *wnd, const KeyMapRange &cmd)
- {
- CommandID executeCommand = kcNull;
- if(wnd != nullptr)
- {
- // Some commands (e.g. open/close/document switching) may invalidate the key map and thus its iterators.
- // To avoid this problem, copy over the elements we are interested in before sending commands.
- std::vector<KeyMap::value_type> commands;
- commands.reserve(std::distance(cmd.first, cmd.second));
- for(auto i = cmd.first; i != cmd.second; i++)
- {
- commands.push_back(*i);
- }
- for(const auto &i : commands)
- {
- m_lastCommands[m_lastCommandPos] = i.second;
- m_lastCommandPos = (m_lastCommandPos + 1) % m_lastCommands.size();
- if(wnd->SendMessage(WM_MOD_KEYCOMMAND, i.second, i.first.AsLPARAM()) != kcNull)
- {
- // Command was handled, no need to let the OS handle the key
- executeCommand = i.second;
- }
- }
- }
- return executeCommand;
- }
- CommandID CInputHandler::GeneralKeyEvent(InputTargetContext context, int code, WPARAM wParam, LPARAM lParam)
- {
- KeyMapRange cmd = { m_keyMap.end(), m_keyMap.end() };
- KeyEventType keyEventType;
- if(code == HC_ACTION)
- {
- //Get the KeyEventType (key up, key down, key repeat)
- DWORD scancode = static_cast<LONG>(lParam) >> 16;
- if((scancode & 0xC000) == 0xC000)
- {
- keyEventType = kKeyEventUp;
- } else if((scancode & 0xC000) == 0x0000)
- {
- keyEventType = kKeyEventDown;
- } else
- {
- keyEventType = kKeyEventRepeat;
- }
- // Catch modifier change (ctrl, alt, shift) - Only check on keyDown or keyUp.
- // NB: we want to catch modifiers even when the input handler is locked
- if(keyEventType == kKeyEventUp || keyEventType == kKeyEventDown)
- {
- scancode = (static_cast<LONG>(lParam) >> 16) & 0x1FF;
- CatchModifierChange(wParam, keyEventType, scancode);
- }
- if(!InterceptSpecialKeys(static_cast<UINT>(wParam), static_cast<LONG>(lParam), true) && !IsBypassed())
- {
- // only execute command when the input handler is not locked
- // and the input is not a consequence of special key interception.
- cmd = m_keyMap.equal_range(KeyCombination(context, m_modifierMask, static_cast<UINT>(wParam), keyEventType));
- }
- }
- if(code == HC_MIDI)
- {
- cmd = m_keyMap.equal_range(KeyCombination(context, ModMidi, static_cast<UINT>(wParam), static_cast<KeyEventType>(lParam)));
- }
- return SendCommands(m_pMainFrm, cmd);
- }
- CommandID CInputHandler::KeyEvent(InputTargetContext context, UINT &nChar, UINT &/*nRepCnt*/, UINT &nFlags, KeyEventType keyEventType, CWnd *pSourceWnd)
- {
- if(InterceptSpecialKeys(nChar, nFlags, false))
- return kcDummyShortcut;
- KeyMapRange cmd = m_keyMap.equal_range(KeyCombination(context, m_modifierMask, nChar, keyEventType));
- if(pSourceWnd == nullptr)
- pSourceWnd = m_pMainFrm; // By default, send command message to main frame.
- return SendCommands(pSourceWnd, cmd);
- }
- // Feature: use Windows keys as modifier keys, intercept special keys
- bool CInputHandler::InterceptSpecialKeys(UINT nChar, UINT nFlags, bool generateMsg)
- {
- KeyEventType keyEventType = GetKeyEventType(HIWORD(nFlags));
- enum { VK_NonExistentKey = VK_F24+1 };
- if(nChar == VK_NonExistentKey)
- {
- return true;
- } else if(m_bInterceptWindowsKeys && (nChar == VK_LWIN || nChar == VK_RWIN))
- {
- if(keyEventType == kKeyEventDown)
- {
- INPUT inp[2];
- inp[0].type = inp[1].type = INPUT_KEYBOARD;
- inp[0].ki.time = inp[1].ki.time = 0;
- inp[0].ki.dwExtraInfo = inp[1].ki.dwExtraInfo = 0;
- inp[0].ki.wVk = inp[1].ki.wVk = VK_NonExistentKey;
- inp[0].ki.wScan = inp[1].ki.wScan = 0;
- inp[0].ki.dwFlags = 0;
- inp[1].ki.dwFlags = KEYEVENTF_KEYUP;
- SendInput(2, inp, sizeof(INPUT));
- }
- }
- if((nChar == VK_NUMLOCK && m_bInterceptNumLock)
- || (nChar == VK_CAPITAL && m_bInterceptCapsLock)
- || (nChar == VK_SCROLL && m_bInterceptScrollLock))
- {
- if(GetMessageExtraInfo() == 0xC0FFEE)
- {
- SetMessageExtraInfo(0);
- return true;
- } else if(keyEventType == kKeyEventDown && generateMsg)
- {
- // Prevent keys from lighting up by simulating a second press.
- INPUT inp[2];
- inp[0].type = inp[1].type = INPUT_KEYBOARD;
- inp[0].ki.time = inp[1].ki.time = 0;
- inp[0].ki.dwExtraInfo = inp[1].ki.dwExtraInfo = 0xC0FFEE;
- inp[0].ki.wVk = inp[1].ki.wVk = static_cast<WORD>(nChar);
- inp[0].ki.wScan = inp[1].ki.wScan = 0;
- inp[0].ki.dwFlags = KEYEVENTF_KEYUP;
- inp[1].ki.dwFlags = 0;
- SendInput(2, inp, sizeof(INPUT));
- }
- }
- return false;
- };
- void CInputHandler::SetupSpecialKeyInterception()
- {
- m_bInterceptWindowsKeys = m_bInterceptNumLock = m_bInterceptCapsLock = m_bInterceptScrollLock = false;
- for(const auto &i : m_keyMap)
- {
- ASSERT(i.second != kcNull);
- if(i.first.Modifier() == ModWin)
- m_bInterceptWindowsKeys = true;
- if(i.first.KeyCode() == VK_NUMLOCK)
- m_bInterceptNumLock = true;
- if(i.first.KeyCode() == VK_CAPITAL)
- m_bInterceptCapsLock = true;
- if(i.first.KeyCode() == VK_SCROLL)
- m_bInterceptScrollLock = true;
- }
- };
- //Deal with Modifier keypresses. Private surouting used above.
- bool CInputHandler::CatchModifierChange(WPARAM wParam, KeyEventType keyEventType, int scancode)
- {
- FlagSet<Modifiers> modifierMask = ModNone;
- // Scancode for right modifier keys should have bit 8 set, but Right Shift is actually 0x36.
- const bool isRight = ((scancode & 0x100) || scancode == 0x36) && TrackerSettings::Instance().MiscDistinguishModifiers;
- switch(wParam)
- {
- case VK_CONTROL:
- modifierMask.set(isRight ? ModRCtrl : ModCtrl);
- break;
- case VK_SHIFT:
- modifierMask.set(isRight ? ModRShift : ModShift);
- break;
- case VK_MENU:
- modifierMask.set(isRight ? ModRAlt : ModAlt);
- break;
- case VK_LWIN: case VK_RWIN: // Feature: use Windows keys as modifier keys
- modifierMask.set(ModWin);
- break;
- }
- if (modifierMask) // This keypress just changed the modifier mask
- {
- if (keyEventType == kKeyEventDown)
- {
- m_modifierMask.set(modifierMask);
- // Right Alt is registered as Ctrl+Alt.
- // Left Ctrl + Right Alt seems like a pretty difficult to use key combination anyway, so just ignore Ctrl.
- if(scancode == 0x138)
- m_modifierMask.reset(ModCtrl);
- #ifdef _DEBUG
- LogModifiers();
- #endif
- } else if (keyEventType == kKeyEventUp)
- m_modifierMask.reset(modifierMask);
- return true;
- }
- return false;
- }
- // Translate MIDI messages to shortcut commands
- CommandID CInputHandler::HandleMIDIMessage(InputTargetContext context, uint32 message)
- {
- auto byte1 = MIDIEvents::GetDataByte1FromEvent(message), byte2 = MIDIEvents::GetDataByte2FromEvent(message);
- switch(MIDIEvents::GetTypeFromEvent(message))
- {
- case MIDIEvents::evControllerChange:
- if(byte2 != 0)
- {
- // Only capture MIDI CCs for now. Some controllers constantly send some MIDI CCs with value 0
- // (e.g. the Roland D-50 sends CC123 whenenver all notes have been released), so we will ignore those.
- return GeneralKeyEvent(context, HC_MIDI, byte1, kKeyEventDown);
- }
- break;
- case MIDIEvents::evNoteOff:
- byte2 = 0;
- [[fallthrough]];
- case MIDIEvents::evNoteOn:
- if(byte2 != 0)
- {
- return GeneralKeyEvent(context, HC_MIDI, byte1 | 0x80, kKeyEventDown);
- } else
- {
- // If the key-down triggered a note, we still want that note to be stopped. So we always pretend that no key was assigned to this event
- GeneralKeyEvent(context, HC_MIDI, byte1 | 0x80, kKeyEventUp);
- }
- break;
- }
- return kcNull;
- }
- int CInputHandler::GetKeyListSize(CommandID cmd) const
- {
- return m_activeCommandSet->GetKeyListSize(cmd);
- }
- //----------------------- Misc
- void CInputHandler::LogModifiers()
- {
- MPT_LOG_GLOBAL(LogDebug, "InputHandler", U_("----------------------------------\n"));
- MPT_LOG_GLOBAL(LogDebug, "InputHandler", m_modifierMask[ModCtrl] ? U_("Ctrl On") : U_("Ctrl --"));
- MPT_LOG_GLOBAL(LogDebug, "InputHandler", m_modifierMask[ModShift] ? U_("\tShft On") : U_("\tShft --"));
- MPT_LOG_GLOBAL(LogDebug, "InputHandler", m_modifierMask[ModAlt] ? U_("\tAlt On") : U_("\tAlt --"));
- MPT_LOG_GLOBAL(LogDebug, "InputHandler", m_modifierMask[ModWin] ? U_("\tWin On\n") : U_("\tWin --\n"));
- }
- KeyEventType CInputHandler::GetKeyEventType(UINT nFlags)
- {
- if (nFlags & TRANSITIONBIT)
- {
- // Key released
- return kKeyEventUp;
- } else if (nFlags & REPEATBIT)
- {
- // Key repeated
- return kKeyEventRepeat;
- } else
- {
- // New key down
- return kKeyEventDown;
- }
- }
- bool CInputHandler::SelectionPressed() const
- {
- int nSelectionKeys = m_activeCommandSet->GetKeyListSize(kcSelect);
- KeyCombination key;
- for (int k=0; k<nSelectionKeys; k++)
- {
- key = m_activeCommandSet->GetKey(kcSelect, k);
- if (m_modifierMask & key.Modifier())
- {
- return true;
- }
- }
- return false;
- }
- bool CInputHandler::ShiftPressed() const
- {
- return m_modifierMask[ModShift | ModRShift];
- }
- bool CInputHandler::CtrlPressed() const
- {
- return m_modifierMask[ModCtrl | ModRCtrl];
- }
- bool CInputHandler::AltPressed() const
- {
- return m_modifierMask[ModAlt | ModRAlt];
- }
- void CInputHandler::Bypass(bool b)
- {
- if(b)
- m_bypassCount++;
- else
- m_bypassCount--;
- ASSERT(m_bypassCount >= 0);
- }
- bool CInputHandler::IsBypassed() const
- {
- return m_bypassCount > 0;
- }
- FlagSet<Modifiers> CInputHandler::GetModifierMask() const
- {
- return m_modifierMask;
- }
- void CInputHandler::SetModifierMask(FlagSet<Modifiers> mask)
- {
- m_modifierMask = mask;
- }
- CString CInputHandler::GetKeyTextFromCommand(CommandID c, const TCHAR *prependText) const
- {
- CString s;
- if(prependText != nullptr)
- {
- s = prependText;
- s.AppendChar(_T('\t'));
- }
- s += m_activeCommandSet->GetKeyTextFromCommand(c, 0);
- return s;
- }
- CString CInputHandler::GetMenuText(UINT id) const
- {
- static constexpr std::tuple<UINT, CommandID, const TCHAR *> MenuItems[] =
- {
- { ID_FILE_NEW, kcFileNew, _T("&New") },
- { ID_FILE_OPEN, kcFileOpen, _T("&Open...") },
- { ID_FILE_OPENTEMPLATE, kcNull, _T("Open &Template") },
- { ID_FILE_CLOSE, kcFileClose, _T("&Close") },
- { ID_FILE_CLOSEALL, kcFileCloseAll, _T("C&lose All") },
- { ID_FILE_APPENDMODULE, kcFileAppend, _T("Appen&d Module...") },
- { ID_FILE_SAVE, kcFileSave, _T("&Save") },
- { ID_FILE_SAVE_AS, kcFileSaveAs, _T("Save &As...") },
- { ID_FILE_SAVE_COPY, kcFileSaveCopy, _T("Save Cop&y...") },
- { ID_FILE_SAVEASTEMPLATE, kcFileSaveTemplate, _T("Sa&ve as Template") },
- { ID_FILE_SAVEASWAVE, kcFileSaveAsWave, _T("Stream Export (&WAV, FLAC, MP3, etc.)...") },
- { ID_FILE_SAVEMIDI, kcFileSaveMidi, _T("Export as M&IDI...") },
- { ID_FILE_SAVEOPL, kcFileSaveOPL, _T("Export O&PL Register Dump...") },
- { ID_FILE_SAVECOMPAT, kcFileExportCompat, _T("Compatibility &Export...") },
- { ID_IMPORT_MIDILIB, kcFileImportMidiLib, _T("Import &MIDI Library...") },
- { ID_ADD_SOUNDBANK, kcFileAddSoundBank, _T("Add Sound &Bank...") },
- { ID_PLAYER_PLAY, kcPlayPauseSong, _T("Pause / &Resume") },
- { ID_PLAYER_PLAYFROMSTART, kcPlaySongFromStart, _T("&Play from Start") },
- { ID_PLAYER_STOP, kcStopSong, _T("&Stop") },
- { ID_PLAYER_PAUSE, kcPauseSong, _T("P&ause") },
- { ID_MIDI_RECORD, kcMidiRecord, _T("&MIDI Record") },
- { ID_ESTIMATESONGLENGTH, kcEstimateSongLength, _T("&Estimate Song Length") },
- { ID_APPROX_BPM, kcApproxRealBPM, _T("Approximate Real &BPM") },
- { ID_EDIT_UNDO, kcEditUndo, _T("&Undo") },
- { ID_EDIT_REDO, kcEditRedo, _T("&Redo") },
- { ID_EDIT_CUT, kcEditCut, _T("Cu&t") },
- { ID_EDIT_COPY, kcEditCopy, _T("&Copy") },
- { ID_EDIT_PASTE, kcEditPaste, _T("&Paste") },
- { ID_EDIT_SELECT_ALL, kcEditSelectAll, _T("Select &All") },
- { ID_EDIT_CLEANUP, kcNull, _T("C&leanup") },
- { ID_EDIT_FIND, kcEditFind, _T("&Find / Replace") },
- { ID_EDIT_FINDNEXT, kcEditFindNext, _T("Find &Next") },
- { ID_EDIT_GOTO_MENU, kcPatternGoto, _T("&Goto") },
- { ID_EDIT_SPLITKEYBOARDSETTINGS, kcShowSplitKeyboardSettings, _T("Split &Keyboard Settings") },
- // "Paste Special" sub menu
- { ID_EDIT_PASTE_SPECIAL, kcEditMixPaste, _T("&Mix Paste") },
- { ID_EDIT_MIXPASTE_ITSTYLE, kcEditMixPasteITStyle, _T("M&ix Paste (IT Style)") },
- { ID_EDIT_PASTEFLOOD, kcEditPasteFlood, _T("Paste Fl&ood") },
- { ID_EDIT_PUSHFORWARDPASTE, kcEditPushForwardPaste, _T("&Push Forward Paste (Insert)") },
- { ID_VIEW_GLOBALS, kcViewGeneral, _T("&General") },
- { ID_VIEW_SAMPLES, kcViewSamples, _T("&Samples") },
- { ID_VIEW_PATTERNS, kcViewPattern, _T("&Patterns") },
- { ID_VIEW_INSTRUMENTS, kcViewInstruments, _T("&Instruments") },
- { ID_VIEW_COMMENTS, kcViewComments, _T("&Comments") },
- { ID_VIEW_OPTIONS, kcViewOptions, _T("S&etup") },
- { ID_VIEW_TOOLBAR, kcViewMain, _T("&Main") },
- { IDD_TREEVIEW, kcViewTree, _T("&Tree") },
- { ID_PLUGIN_SETUP, kcViewAddPlugin, _T("Pl&ugin Manager") },
- { ID_CHANNEL_MANAGER, kcViewChannelManager, _T("Ch&annel Manager") },
- { ID_CLIPBOARD_MANAGER, kcToggleClipboardManager, _T("C&lipboard Manager") },
- { ID_VIEW_SONGPROPERTIES, kcViewSongProperties, _T("Song P&roperties") },
- { ID_PATTERN_MIDIMACRO, kcShowMacroConfig, _T("&Zxx Macro Configuration") },
- { ID_VIEW_MIDIMAPPING, kcViewMIDImapping, _T("&MIDI Mapping") },
- { ID_VIEW_EDITHISTORY, kcViewEditHistory, _T("Edit &History") },
- // Help submenu
- { ID_HELPSHOW, kcHelp, _T("&Help") },
- { ID_EXAMPLE_MODULES, kcNull, _T("&Example Modules") },
- };
- for(const auto & [cmdID, command, text] : MenuItems)
- {
- if(id == cmdID)
- {
- if(command != kcNull)
- return GetKeyTextFromCommand(command, text);
- else
- return text;
- }
- }
- MPT_ASSERT_NOTREACHED();
- return _T("Unknown Item");
- }
- void CInputHandler::UpdateMainMenu()
- {
- CMenu *pMenu = (CMainFrame::GetMainFrame())->GetMenu();
- if (!pMenu) return;
- pMenu->GetSubMenu(0)->ModifyMenu(0, MF_BYPOSITION | MF_STRING, 0, GetMenuText(ID_FILE_NEW));
- static constexpr int MenuItems[] =
- {
- ID_FILE_OPEN,
- ID_FILE_APPENDMODULE,
- ID_FILE_CLOSE,
- ID_FILE_SAVE,
- ID_FILE_SAVE_AS,
- ID_FILE_SAVEASWAVE,
- ID_FILE_SAVEMIDI,
- ID_FILE_SAVECOMPAT,
- ID_IMPORT_MIDILIB,
- ID_ADD_SOUNDBANK,
- ID_PLAYER_PLAY,
- ID_PLAYER_PLAYFROMSTART,
- ID_PLAYER_STOP,
- ID_PLAYER_PAUSE,
- ID_MIDI_RECORD,
- ID_ESTIMATESONGLENGTH,
- ID_APPROX_BPM,
- ID_EDIT_UNDO,
- ID_EDIT_REDO,
- ID_EDIT_CUT,
- ID_EDIT_COPY,
- ID_EDIT_PASTE,
- ID_EDIT_PASTE_SPECIAL,
- ID_EDIT_MIXPASTE_ITSTYLE,
- ID_EDIT_PASTEFLOOD,
- ID_EDIT_PUSHFORWARDPASTE,
- ID_EDIT_SELECT_ALL,
- ID_EDIT_FIND,
- ID_EDIT_FINDNEXT,
- ID_EDIT_GOTO_MENU,
- ID_EDIT_SPLITKEYBOARDSETTINGS,
- ID_VIEW_GLOBALS,
- ID_VIEW_SAMPLES,
- ID_VIEW_PATTERNS,
- ID_VIEW_INSTRUMENTS,
- ID_VIEW_COMMENTS,
- ID_VIEW_TOOLBAR,
- IDD_TREEVIEW,
- ID_VIEW_OPTIONS,
- ID_PLUGIN_SETUP,
- ID_CHANNEL_MANAGER,
- ID_CLIPBOARD_MANAGER,
- ID_VIEW_SONGPROPERTIES,
- ID_VIEW_SONGPROPERTIES,
- ID_PATTERN_MIDIMACRO,
- ID_VIEW_EDITHISTORY,
- ID_HELPSHOW,
- };
- for(const auto id : MenuItems)
- {
- pMenu->ModifyMenu(id, MF_BYCOMMAND | MF_STRING, id, GetMenuText(id));
- }
- }
- void CInputHandler::SetNewCommandSet(const CCommandSet *newSet)
- {
- m_activeCommandSet->Copy(newSet);
- m_activeCommandSet->GenKeyMap(m_keyMap);
- SetupSpecialKeyInterception(); // Feature: use Windows keys as modifier keys, intercept special keys
- UpdateMainMenu();
- }
- bool CInputHandler::SetEffectLetters(const CModSpecifications &modSpecs)
- {
- MPT_LOG_GLOBAL(LogDebug, "InputHandler", U_("Changing command set."));
- bool retval = m_activeCommandSet->QuickChange_SetEffects(modSpecs);
- if(retval) m_activeCommandSet->GenKeyMap(m_keyMap);
- return retval;
- }
- bool CInputHandler::IsKeyPressHandledByTextBox(DWORD key, HWND hWnd) const
- {
- if(hWnd == nullptr)
- return false;
-
- TCHAR activeWindowClassName[6];
- GetClassName(hWnd, activeWindowClassName, mpt::saturate_cast<int>(std::size(activeWindowClassName)));
- const bool textboxHasFocus = _tcsicmp(activeWindowClassName, _T("Edit")) == 0;
- if(!textboxHasFocus)
- return false;
- //Alpha-numerics (only shift or no modifier):
- if(!GetModifierMask().test_any_except(ModShift)
- && ((key>='A'&&key<='Z') || (key>='0'&&key<='9') ||
- key==VK_DIVIDE || key==VK_MULTIPLY || key==VK_SPACE || key==VK_RETURN ||
- key==VK_CAPITAL || (key>=VK_OEM_1 && key<=VK_OEM_3) || (key>=VK_OEM_4 && key<=VK_OEM_8)))
- return true;
- //navigation (any modifier):
- if(key == VK_LEFT || key == VK_RIGHT || key == VK_UP || key == VK_DOWN ||
- key == VK_HOME || key == VK_END || key == VK_DELETE || key == VK_INSERT || key == VK_BACK)
- return true;
- //Copy paste etc..
- if(GetModifierMask() == ModCtrl &&
- (key == 'Y' || key == 'Z' || key == 'X' || key == 'C' || key == 'V' || key == 'A'))
- return true;
- return false;
- }
- BypassInputHandler::BypassInputHandler()
- {
- if(CMainFrame::GetInputHandler())
- {
- bypassed = true;
- CMainFrame::GetInputHandler()->Bypass(true);
- }
- }
- BypassInputHandler::~BypassInputHandler()
- {
- if(bypassed)
- {
- CMainFrame::GetInputHandler()->Bypass(false);
- bypassed = false;
- }
- }
- OPENMPT_NAMESPACE_END
|