diff --git a/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx b/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx index 84fdcfa84f3f..a6fe6f2d62a7 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx +++ b/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx @@ -220,6 +220,15 @@ All apps + + Path to program + + + Arguments for program + + + Start in direcotry + Remapping successful diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyboardManagerEditorStrings.h b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyboardManagerEditorStrings.h index d64207540256..38e7d2bdfae8 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyboardManagerEditorStrings.h +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/KeyboardManagerEditorStrings.h @@ -27,6 +27,21 @@ namespace KeyboardManagerEditorStrings return GET_RESOURCE_STRING(IDS_MAPPING_TYPE_DROPDOWN_RUN_PROGRAM); } + inline std::wstring EditShortcutsPathToProgram() + { + return GET_RESOURCE_STRING(IDS_EDITSHORTCUTS_PATHTOPROGRAM); + } + + inline std::wstring EditShortcutsArgsForProgram() + { + return GET_RESOURCE_STRING(IDS_EDITSHORTCUTS_ARGSFORPROGRAM); + } + + inline std::wstring EditShortcutsStartInDirForProgram() + { + return GET_RESOURCE_STRING(IDS_EDITSHORTCUTS_STARTINDIRFORPROGRAM); + } + // Function to return the error message winrt::hstring GetErrorMessage(ShortcutErrorType errorType); -} +} \ No newline at end of file diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/ShortcutControl.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/ShortcutControl.cpp index cac259aa9687..3681b65334b4 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/ShortcutControl.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/ShortcutControl.cpp @@ -158,11 +158,14 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector(); - auto text = textbox.Text(); - uint32_t rowIndex = -1; + auto runProgramArgsForProgramInput = TextBox(); + //runProgramArgsForProgramInput.PlaceholderText(KeyboardManagerEditorStrings::EditShortcutsArgsForProgram()); + //runProgramArgsForProgramInput.Margin(runProgramPathInputMargin); + + //runProgramArgsForProgramInput.AcceptsReturn(false); + //runProgramArgsForProgramInput.Visibility(Visibility::Collapsed); + //runProgramArgsForProgramInput.Width(EditorConstants::TableDropDownHeight); + //controlStackPanel.Children().Append(runProgramArgsForProgramInput); + //runProgramArgsForProgramInput.HorizontalAlignment(HorizontalAlignment::Left); + + //auto runProgramStartInDirInput = TextBox(); + //runProgramPathInput.PlaceholderText(KeyboardManagerEditorStrings::EditShortcutsStartInDirForProgram()); + //runProgramStartInDirInput.Margin(runProgramPathInputMargin); + //runProgramStartInDirInput.AcceptsReturn(false); + //runProgramStartInDirInput.Visibility(Visibility::Collapsed); + //runProgramStartInDirInput.Width(EditorConstants::TableDropDownHeight); + //controlStackPanel.Children().Append(runProgramStartInDirInput); + //runProgramStartInDirInput.HorizontalAlignment(HorizontalAlignment::Left); + + runProgramPathInput.TextChanged([parent, row, runProgramPathInput, runProgramArgsForProgramInput](winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::TextChangedEventArgs const& e) mutable { + uint32_t rowIndex = -1; if (!parent.Children().IndexOf(row, rowIndex)) { return; @@ -183,11 +203,51 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vectorshortcutDropDownVariableSizedWrapGrid.as(); auto gridMargin = Windows::UI::Xaml::Thickness(); @@ -245,13 +305,9 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector(newKeys); if (shortCut.isRunProgram) { - Shortcut tempShortcut; isRunProgram = true; - tempShortcut.isRunProgram = true; - tempShortcut.runProgramPath = runProgramPathInput.Text().c_str(); - // Assign instead of setting the value in the buffer since the previous value may not be a Shortcut - //shortcutRemapBuffer[index].first[1] = tempShortcut; - runProgramPathInput.Text(shortCut.runProgramPath); + runProgramPathInput.Text(shortCut.runProgramFilePath); + runProgramArgsForProgramInput.Text(shortCut.runProgramArgs); typeCombo.SelectedIndex(2); } else @@ -469,6 +525,29 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector& keys); diff --git a/src/runner/centralized_kb_hook.cpp b/src/runner/centralized_kb_hook.cpp index 9cbd860ac537..3620686e1a76 100644 --- a/src/runner/centralized_kb_hook.cpp +++ b/src/runner/centralized_kb_hook.cpp @@ -18,13 +18,12 @@ namespace CentralizedKeyboardHook { - - class RunProgramSpec2 + class RunProgramSpec { private: // Function to split a wstring based on a delimiter and return a vector of split strings - + std::vector splitwstring(const std::wstring& input, wchar_t delimiter); inline auto comparator() const @@ -32,7 +31,7 @@ namespace CentralizedKeyboardHook return std::make_tuple(winKey, ctrlKey, altKey, shiftKey, actionKey); } - std::vector RunProgramSpec2::splitwstringOnChar(const std::wstring& input, wchar_t delimiter) + std::vector RunProgramSpec::splitwstringOnChar(const std::wstring& input, wchar_t delimiter) { std::wstringstream ss(input); std::wstring item; @@ -45,7 +44,7 @@ namespace CentralizedKeyboardHook return splittedStrings; } - bool RunProgramSpec2::SetKey(const DWORD input) + bool RunProgramSpec::SetKey(const DWORD input) { // Since there isn't a key for a common Win key we use the key code defined by us if (input == CommonSharedConstants::VK_WIN_BOTH) @@ -188,7 +187,6 @@ namespace CentralizedKeyboardHook } public: - ModifierKey winKey = ModifierKey::Disabled; ModifierKey ctrlKey = ModifierKey::Disabled; ModifierKey altKey = ModifierKey::Disabled; @@ -201,7 +199,7 @@ namespace CentralizedKeyboardHook std::vector keys; DWORD actionKey = {}; - RunProgramSpec2::RunProgramSpec2(const std::wstring& shortcutVK, const std::wstring& targetAppSpec) : + RunProgramSpec::RunProgramSpec(const std::wstring& shortcutVK, const std::wstring& runProgram, const std::wstring& runProgramArgs, const std::wstring& runProgramStartInDir) : winKey(ModifierKey::Disabled), ctrlKey(ModifierKey::Disabled), altKey(ModifierKey::Disabled), shiftKey(ModifierKey::Disabled), actionKey(NULL) { auto _keys = splitwstringOnChar(shortcutVK, ';'); @@ -211,12 +209,9 @@ namespace CentralizedKeyboardHook SetKey(vkKeyCode); } - //auto KBM_RUN_PROGRAM_DELIMITER = L"<|||>"; - //auto targetParts = splitwStringOnString(targetAppSpec, KBM_RUN_PROGRAM_DELIMITER, false); - - path = targetAppSpec; - //args = targetParts[1]; - //dir = targetParts[2]; + path = runProgram; + args = runProgramArgs; + dir = runProgramStartInDir; } }; @@ -419,7 +414,7 @@ namespace CentralizedKeyboardHook bool getConfigInit = false; bool runProgramEnabled = true; - std::vector runProgramSpecs; + std::vector runProgramSpecs; void SetRunProgramEnabled(bool enabled) { @@ -479,8 +474,11 @@ namespace CentralizedKeyboardHook if (isRunProgram) { - auto runProgram = it.GetObjectW().GetNamedString(KeyboardManagerConstants::RunProgramSettingName, L""); - auto runProgramSpec = RunProgramSpec2(originalKeys.c_str(), runProgram.c_str()); + auto runProgram = it.GetObjectW().GetNamedString(KeyboardManagerConstants::RunProgramFilePathSettingName, L""); + auto runProgramArgs = it.GetObjectW().GetNamedString(KeyboardManagerConstants::RunProgramArgsSettingName, L""); + auto runProgramStartInDir = it.GetObjectW().GetNamedString(KeyboardManagerConstants::RunProgramStartInDirSettingName, L""); + + auto runProgramSpec = RunProgramSpec(originalKeys.c_str(), runProgram.c_str(), runProgramArgs.c_str(), runProgramStartInDir.c_str()); runProgramSpecs.push_back(runProgramSpec); } } @@ -497,7 +495,7 @@ namespace CentralizedKeyboardHook bool isPartOfAnyRunProgramSpec2(DWORD key) { - for (RunProgramSpec2 runProgramSpec : runProgramSpecs) + for (RunProgramSpec runProgramSpec : runProgramSpecs) { if (runProgramSpec.actionKey == key) { @@ -515,7 +513,7 @@ namespace CentralizedKeyboardHook return false; } - bool isPartOfThisRunProgramSpec2(RunProgramSpec2 runProgramSpec, DWORD key) + bool isPartOfThisRunProgramSpec2(RunProgramSpec runProgramSpec, DWORD key) { for (DWORD c : runProgramSpec.keys) { @@ -528,8 +526,7 @@ namespace CentralizedKeyboardHook } void HandleCreateProcessHotKeysAndChords(LocalKey hotkey) - { - + { if (!runProgramEnabled) { return; @@ -550,7 +547,7 @@ namespace CentralizedKeyboardHook return; } - for (RunProgramSpec2 runProgramSpec : runProgramSpecs) + for (RunProgramSpec runProgramSpec : runProgramSpecs) { if ( (runProgramSpec.winKey == ModifierKey::Disabled || (runProgramSpec.winKey == ModifierKey::Left && hotkey.l_win)) && (runProgramSpec.shiftKey == ModifierKey::Disabled || (runProgramSpec.shiftKey == ModifierKey::Left && hotkey.l_shift)) && (runProgramSpec.altKey == ModifierKey::Disabled || (runProgramSpec.altKey == ModifierKey::Left && hotkey.l_alt)) && (runProgramSpec.ctrlKey == ModifierKey::Disabled || (runProgramSpec.ctrlKey == ModifierKey::Left && hotkey.l_control))) diff --git a/src/runner/centralized_kb_hook.h b/src/runner/centralized_kb_hook.h index 522498d29d10..69a415cdfd05 100644 --- a/src/runner/centralized_kb_hook.h +++ b/src/runner/centralized_kb_hook.h @@ -33,6 +33,7 @@ namespace CentralizedKeyboardHook void AddPressedKeyAction(const std::wstring& moduleName, const DWORD vk, const UINT milliseconds, std::function&& action) noexcept; void ClearModuleHotkeys(const std::wstring& moduleName) noexcept; void RegisterWindow(HWND hwnd) noexcept; + void RefreshConfig(); DWORD GetProcessIdByName(const std::wstring& processName); std::wstring GetFileNameFromPath(const std::wstring& fullPath); HWND find_main_window(unsigned long process_id); diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 7749fc9f171c..a46e1b05500a 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -47,6 +47,8 @@ #include #include +#include + // disabling warning 4458 - declaration of 'identifier' hides class member // to avoid warnings from GDI files - can't add winRT directory to external code // in the Cpp.Build.props @@ -89,6 +91,71 @@ void open_menu_from_another_instance(std::optional settings_window) PostMessageW(hwnd_main, WM_COMMAND, ID_SETTINGS_MENU_COMMAND, msg); } +DWORD WINAPI WatchKeyboardManagerConfigs(LPVOID lpParameter) +{ + // don't need but can't not use + if (lpParameter) + { + } + + //HANDLE PowertoyModule::hWatchDirectory = nullptr; + + //// make sure we don't have more than one + //if (PowertoyModule::hWatchDirectory != nullptr) + //{ + // return 1; + //} + + auto directoryPath = PTSettingsHelper::get_module_save_folder_location(KeyboardManagerConstants::ModuleName); + + auto hWatchDirectory = CreateFile( + directoryPath.c_str(), + FILE_LIST_DIRECTORY, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if (hWatchDirectory == INVALID_HANDLE_VALUE) + { + Logger::trace(L"Error: Unable to open directory {}", directoryPath); + return 1; + } + + DWORD dwBufferSize = 4096; + BYTE* pbBuffer = new BYTE[dwBufferSize]; + DWORD bytesReturned; + + while (true) + { + // ReadDirectoryChangesW is fired twice per write and in this case it does not matter since we're just doing a reset of data, no real work. + if (ReadDirectoryChangesW( + hWatchDirectory, + pbBuffer, + sizeof(pbBuffer), + FALSE, + FILE_NOTIFY_CHANGE_LAST_WRITE, + &bytesReturned, + NULL, + NULL)) + { + // we don't really care what changed, just refresh + CentralizedKeyboardHook::RefreshConfig(); + continue; + } + else + { + Logger::trace(L"Error: Unable to read directory changes."); + break; + } + } + + CloseHandle(hWatchDirectory); + + return 0; +} + int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe) { Logger::info("Runner is starting. Elevated={} openOobe={} openScoobe={}", isProcessElevated, openOobe, openScoobe); @@ -210,6 +277,10 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow } settings_telemetry::init(); + + // start WatchKeyboardManagerConfigs + CreateThread(NULL, 0, WatchKeyboardManagerConfigs, 0, 0, NULL); + result = run_message_loop(); } catch (std::runtime_error& err)