#include "pch.h" #include "KeyboardManagerEditorLibraryWrapper.h" #include #include #include #include #include #include #include #include #include extern "C" { void* CreateMappingConfiguration() { return new MappingConfiguration(); } void DestroyMappingConfiguration(void* config) { delete static_cast(config); } bool LoadMappingSettings(void* config) { return static_cast(config)->LoadSettings(); } bool SaveMappingSettings(void* config) { return static_cast(config)->SaveSettingsToFile(); } wchar_t* AllocateAndCopyString(const std::wstring& str) { size_t len = str.length(); wchar_t* buffer = new wchar_t[len + 1]; wcscpy_s(buffer, len + 1, str.c_str()); return buffer; } int GetSingleKeyRemapCount(void* config) { auto mapping = static_cast(config); return static_cast(mapping->singleKeyReMap.size()); } bool GetSingleKeyRemap(void* config, int index, SingleKeyMapping* mapping) { auto mappingConfig = static_cast(config); std::vector> allMappings; for (const auto& kv : mappingConfig->singleKeyReMap) { allMappings.push_back(kv); } if (index < 0 || index >= allMappings.size()) { return false; } const auto& kv = allMappings[index]; mapping->originalKey = static_cast(kv.first); // Remap to single key if (kv.second.index() == 0) { mapping->targetKey = AllocateAndCopyString(std::to_wstring(std::get(kv.second))); mapping->isShortcut = false; } // Remap to shortcut else if (kv.second.index() == 1) { mapping->targetKey = AllocateAndCopyString(std::get(kv.second).ToHstringVK().c_str()); mapping->isShortcut = true; } else { mapping->targetKey = AllocateAndCopyString(L""); mapping->isShortcut = false; } return true; } int GetSingleKeyToTextRemapCount(void* config) { auto mapping = static_cast(config); return static_cast(mapping->singleKeyToTextReMap.size()); } bool GetSingleKeyToTextRemap(void* config, int index, KeyboardTextMapping* mapping) { auto mappingConfig = static_cast(config); if (index < 0 || index >= mappingConfig->singleKeyToTextReMap.size()) { return false; } auto it = mappingConfig->singleKeyToTextReMap.begin(); std::advance(it, index); mapping->originalKey = static_cast(it->first); std::wstring text = std::get(it->second); mapping->targetText = AllocateAndCopyString(text); return true; } int GetShortcutRemapCountByType(void* config, int operationType) { auto mapping = static_cast(config); int count = 0; for (const auto& kv : mapping->osLevelShortcutReMap) { bool shouldCount = false; if (operationType == 0) { if ((kv.second.targetShortcut.index() == 0) || (kv.second.targetShortcut.index() == 1 && std::get(kv.second.targetShortcut).operationType == Shortcut::OperationType::RemapShortcut)) { shouldCount = true; } } else if (operationType == 1) { if (kv.second.targetShortcut.index() == 1 && std::get(kv.second.targetShortcut).operationType == Shortcut::OperationType::RunProgram) { shouldCount = true; } } else if (operationType == 2) { if (kv.second.targetShortcut.index() == 1 && std::get(kv.second.targetShortcut).operationType == Shortcut::OperationType::OpenURI) { shouldCount = true; } } else if (operationType == 3) { if (kv.second.targetShortcut.index() == 2) { shouldCount = true; } } if (shouldCount) { count++; } } for (const auto& appMap : mapping->appSpecificShortcutReMap) { for (const auto& shortcutKv : appMap.second) { bool shouldCount = false; if (operationType == 0) { if ((shortcutKv.second.targetShortcut.index() == 0) || (shortcutKv.second.targetShortcut.index() == 1 && std::get(shortcutKv.second.targetShortcut).operationType == Shortcut::OperationType::RemapShortcut)) { shouldCount = true; } } else if (operationType == 1) { if (shortcutKv.second.targetShortcut.index() == 1 && std::get(shortcutKv.second.targetShortcut).operationType == Shortcut::OperationType::RunProgram) { shouldCount = true; } } else if (operationType == 2) { if (shortcutKv.second.targetShortcut.index() == 1 && std::get(shortcutKv.second.targetShortcut).operationType == Shortcut::OperationType::OpenURI) { shouldCount = true; } } else if (operationType == 3) { if (shortcutKv.second.targetShortcut.index() == 2) { shouldCount = true; } } if (shouldCount) { count++; } } } return count; } bool GetShortcutRemapByType(void* config, int operationType, int index, ShortcutMapping* mapping) { auto mappingConfig = static_cast(config); std::vector> filteredMappings; for (const auto& kv : mappingConfig->osLevelShortcutReMap) { bool shouldAdd = false; switch (operationType) { case 0: // RemapShortcut if ((kv.second.targetShortcut.index() == 0) || (kv.second.targetShortcut.index() == 1 && std::get(kv.second.targetShortcut).operationType == Shortcut::OperationType::RemapShortcut)) { shouldAdd = true; } break; case 1: // RunProgram if (kv.second.targetShortcut.index() == 1 && std::get(kv.second.targetShortcut).operationType == Shortcut::OperationType::RunProgram) { shouldAdd = true; } break; case 2: // OpenURI if (kv.second.targetShortcut.index() == 1 && std::get(kv.second.targetShortcut).operationType == Shortcut::OperationType::OpenURI) { shouldAdd = true; } break; case 3: if (kv.second.targetShortcut.index() == 2) { shouldAdd = true; } break; default: break; } if (shouldAdd) { filteredMappings.push_back(std::make_tuple(kv.first, kv.second.targetShortcut, L"")); } } for (const auto& appKv : mappingConfig->appSpecificShortcutReMap) { for (const auto& shortcutKv : appKv.second) { bool shouldAdd = false; switch (operationType) { case 0: // RemapShortcut if ((shortcutKv.second.targetShortcut.index() == 0) || (shortcutKv.second.targetShortcut.index() == 1 && std::get(shortcutKv.second.targetShortcut).operationType == Shortcut::OperationType::RemapShortcut)) { shouldAdd = true; } break; case 1: // RunProgram if (shortcutKv.second.targetShortcut.index() == 1 && std::get(shortcutKv.second.targetShortcut).operationType == Shortcut::OperationType::RunProgram) { shouldAdd = true; } break; case 2: // OpenURI if (shortcutKv.second.targetShortcut.index() == 1 && std::get(shortcutKv.second.targetShortcut).operationType == Shortcut::OperationType::OpenURI) { shouldAdd = true; } break; case 3: if (shortcutKv.second.targetShortcut.index() == 2) { shouldAdd = true; } break; default: break; } if (shouldAdd) { filteredMappings.push_back(std::make_tuple( shortcutKv.first, shortcutKv.second.targetShortcut, appKv.first)); } } } if (index < 0 || index >= filteredMappings.size()) { return false; } const auto& [origShortcut, targetShortcutUnion, app] = filteredMappings[index]; std::wstring origKeysStr = origShortcut.ToHstringVK().c_str(); mapping->originalKeys = AllocateAndCopyString(origKeysStr); mapping->targetApp = AllocateAndCopyString(app); if (targetShortcutUnion.index() == 0) { DWORD targetKey = std::get(targetShortcutUnion); mapping->targetKeys = AllocateAndCopyString(std::to_wstring(targetKey)); mapping->operationType = 0; mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(L""); } else if (targetShortcutUnion.index() == 1) { Shortcut targetShortcut = std::get(targetShortcutUnion); std::wstring targetKeysStr = targetShortcut.ToHstringVK().c_str(); mapping->operationType = static_cast(targetShortcut.operationType); switch (targetShortcut.operationType) { case Shortcut::OperationType::RunProgram: mapping->targetKeys = AllocateAndCopyString(targetKeysStr); mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(targetShortcut.runProgramFilePath); mapping->programArgs = AllocateAndCopyString(targetShortcut.runProgramArgs); mapping->uriToOpen = AllocateAndCopyString(L""); break; case Shortcut::OperationType::OpenURI: mapping->targetKeys = AllocateAndCopyString(targetKeysStr); mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(targetShortcut.uriToOpen); break; default: mapping->targetKeys = AllocateAndCopyString(targetKeysStr); mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(L""); break; } } else if (targetShortcutUnion.index() == 2) { std::wstring text = std::get(targetShortcutUnion); mapping->targetKeys = AllocateAndCopyString(L""); mapping->operationType = 0; mapping->targetText = AllocateAndCopyString(text); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(L""); } return true; } int GetShortcutRemapCount(void* config) { auto mapping = static_cast(config); int count = static_cast(mapping->osLevelShortcutReMap.size()); for (const auto& appMap : mapping->appSpecificShortcutReMap) { count += static_cast(appMap.second.size()); } return count; } bool GetShortcutRemap(void* config, int index, ShortcutMapping* mapping) { auto mappingConfig = static_cast(config); std::vector> allMappings; for (const auto& kv : mappingConfig->osLevelShortcutReMap) { allMappings.push_back(std::make_tuple(kv.first, kv.second.targetShortcut, L"")); } for (const auto& appKv : mappingConfig->appSpecificShortcutReMap) { for (const auto& shortcutKv : appKv.second) { allMappings.push_back(std::make_tuple( shortcutKv.first, shortcutKv.second.targetShortcut, appKv.first)); } } if (index < 0 || index >= allMappings.size()) { return false; } const auto& [origShortcut, targetShortcutUnion, app] = allMappings[index]; std::wstring origKeysStr = origShortcut.ToHstringVK().c_str(); mapping->originalKeys = AllocateAndCopyString(origKeysStr); mapping->targetApp = AllocateAndCopyString(app); if (targetShortcutUnion.index() == 0) { DWORD targetKey = std::get(targetShortcutUnion); mapping->targetKeys = AllocateAndCopyString(std::to_wstring(targetKey)); mapping->operationType = 0; mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(L""); } else if (targetShortcutUnion.index() == 1) { Shortcut targetShortcut = std::get(targetShortcutUnion); std::wstring targetKeysStr = targetShortcut.ToHstringVK().c_str(); mapping->operationType = static_cast(targetShortcut.operationType); if (targetShortcut.operationType == Shortcut::OperationType::RunProgram) { mapping->targetKeys = AllocateAndCopyString(targetKeysStr); mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(targetShortcut.runProgramFilePath); mapping->programArgs = AllocateAndCopyString(targetShortcut.runProgramArgs); mapping->uriToOpen = AllocateAndCopyString(L""); } else if (targetShortcut.operationType == Shortcut::OperationType::OpenURI) { mapping->targetKeys = AllocateAndCopyString(targetKeysStr); mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(targetShortcut.uriToOpen); } else { mapping->targetKeys = AllocateAndCopyString(targetKeysStr); mapping->targetText = AllocateAndCopyString(L""); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(L""); } } else if (targetShortcutUnion.index() == 2) { std::wstring text = std::get(targetShortcutUnion); mapping->targetKeys = AllocateAndCopyString(L""); mapping->operationType = 0; mapping->targetText = AllocateAndCopyString(text); mapping->programPath = AllocateAndCopyString(L""); mapping->programArgs = AllocateAndCopyString(L""); mapping->uriToOpen = AllocateAndCopyString(L""); } return true; } void FreeString(wchar_t* str) { delete[] str; } bool AddSingleKeyRemap(void* config, int originalKey, int targetKey) { auto mappingConfig = static_cast(config); return mappingConfig->AddSingleKeyRemap(static_cast(originalKey), static_cast(targetKey)); } bool AddSingleKeyToTextRemap(void* config, int originalKey, const wchar_t* text) { auto mappingConfig = static_cast(config); if (text == nullptr) { return false; } return mappingConfig->AddSingleKeyToTextRemap(static_cast(originalKey), text); } bool AddSingleKeyToShortcutRemap(void* config, int originalKey, const wchar_t* targetKeys) { auto mappingConfig = static_cast(config); if (!targetKeys) { return false; } Shortcut targetShortcut(targetKeys); return mappingConfig->AddSingleKeyRemap(static_cast(originalKey), targetShortcut); } bool AddShortcutRemap(void* config, const wchar_t* originalKeys, const wchar_t* targetKeys, const wchar_t* targetApp, int operationType, const wchar_t* appPathOrUri, const wchar_t* args, const wchar_t* startDirectory, int elevation, int ifRunningAction, int visibility) { auto mappingConfig = static_cast(config); Shortcut originalShortcut(originalKeys); KeyShortcutTextUnion targetShortcut; switch (operationType) { case 1: targetShortcut = Shortcut(targetKeys); std::get(targetShortcut).runProgramFilePath = std::wstring(appPathOrUri); if (args) { std::get(targetShortcut).runProgramArgs = std::wstring(args); } if (startDirectory) { std::get(targetShortcut).runProgramStartInDir = std::wstring(startDirectory); } std::get(targetShortcut).elevationLevel = static_cast(elevation); std::get(targetShortcut).alreadyRunningAction = static_cast(ifRunningAction); std::get(targetShortcut).startWindowType = static_cast(visibility); std::get(targetShortcut).operationType = static_cast(operationType); break; case 2: targetShortcut = Shortcut(targetKeys); std::get(targetShortcut).uriToOpen = std::wstring(appPathOrUri); std::get(targetShortcut).operationType = static_cast(operationType); break; case 3: targetShortcut = std::wstring(targetKeys); break; default: targetShortcut = Shortcut(targetKeys); std::get(targetShortcut).operationType = static_cast(operationType); break; } std::wstring app(targetApp ? targetApp : L""); if (app.empty()) { return mappingConfig->AddOSLevelShortcut(originalShortcut, targetShortcut); } else { return mappingConfig->AddAppSpecificShortcut(app, originalShortcut, targetShortcut); } } void GetKeyDisplayName(int keyCode, wchar_t* keyName, int maxCount) { if (keyName == nullptr || maxCount <= 0) { return; } LayoutMap layoutMap; std::wstring name = layoutMap.GetKeyName(static_cast(keyCode)); wcsncpy_s(keyName, maxCount, name.c_str(), _TRUNCATE); } int GetKeyCodeFromName(const wchar_t* keyName) { Logger::info(L"Getting key code for key name: {0}", keyName ? keyName : L"null"); if (keyName == nullptr) { return 0; } LayoutMap layoutMap; std::wstring name(keyName); int keyCode = static_cast(layoutMap.GetKeyFromName(name)); Logger::info(L"Key code for key name {0}: {1}", keyName, keyCode); return keyCode; } // Function to get the type of a key (Win, Ctrl, Alt, Shift, or Action) int GetKeyType(int key) { return static_cast(Helpers::GetKeyType(static_cast(key))); } // Function to check if a shortcut is illegal bool IsShortcutIllegal(const wchar_t* shortcutKeys) { Logger::info(L"Checking if shortcut is illegal: {0}", shortcutKeys ? shortcutKeys : L"null"); if (!shortcutKeys) { return false; } Shortcut shortcut(shortcutKeys); ShortcutErrorType result = EditorHelpers::IsShortcutIllegal(shortcut); // Return true if an error was detected (anything other than NoError) return result != ShortcutErrorType::NoError; } // Function to check if two shortcuts are equal bool AreShortcutsEqual(const wchar_t* lShort, const wchar_t* rShort) { if (!lShort || !rShort) { return false; } Shortcut lhs(lShort); Shortcut rhs(rShort); return lhs == rhs; } // Function to delete a single key remapping bool DeleteSingleKeyRemap(void* config, int originalKey) { auto mappingConfig = static_cast(config); // Find and delete the single key remapping auto it = mappingConfig->singleKeyReMap.find(static_cast(originalKey)); if (it != mappingConfig->singleKeyReMap.end()) { mappingConfig->singleKeyReMap.erase(it); return true; } return false; } bool DeleteSingleKeyToTextRemap(void* config, int originalKey) { auto mappingConfig = static_cast(config); auto it = mappingConfig->singleKeyToTextReMap.find(originalKey); if (it != mappingConfig->singleKeyToTextReMap.end()) { mappingConfig->singleKeyToTextReMap.erase(it); return true; } return false; } // Function to delete a shortcut remapping bool DeleteShortcutRemap(void* config, const wchar_t* originalKeys, const wchar_t* targetApp) { auto mappingConfig = static_cast(config); if (originalKeys == nullptr) { return false; } std::wstring appName = targetApp ? targetApp : L""; Shortcut shortcut(originalKeys); // Determine the type of remapping to delete based on the app name if (appName.empty()) { // Delete OS level shortcut mapping auto it = mappingConfig->osLevelShortcutReMap.find(shortcut); if (it != mappingConfig->osLevelShortcutReMap.end()) { mappingConfig->osLevelShortcutReMap.erase(it); return true; } } else { // Delete app-specific shortcut mapping auto appIt = mappingConfig->appSpecificShortcutReMap.find(appName); if (appIt != mappingConfig->appSpecificShortcutReMap.end()) { auto shortcutIt = appIt->second.find(shortcut); if (shortcutIt != appIt->second.end()) { appIt->second.erase(shortcutIt); // If the app-specific mapping is empty, remove the app entry if (appIt->second.empty()) { mappingConfig->appSpecificShortcutReMap.erase(appIt); } return true; } } } return false; } } // Get the list of keyboard keys in Editor int GetKeyboardKeysList(bool isShortcut, KeyNamePair* keyList, int maxCount) { if (keyList == nullptr || maxCount <= 0) { return 0; } LayoutMap layoutMap; auto keyNameList = layoutMap.GetKeyNameList(isShortcut); int count = (std::min)(static_cast(keyNameList.size()), maxCount); // Transfer the key list to the output struct format for (int i = 0; i < count; ++i) { keyList[i].keyCode = static_cast(keyNameList[i].first); wcsncpy_s(keyList[i].keyName, keyNameList[i].second.c_str(), _countof(keyList[i].keyName) - 1); } return count; }