diff --git a/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs b/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs index eb89dc8d66..d1a0e912a8 100644 --- a/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs +++ b/src/modules/poweraccent/PowerAccent.Core/PowerAccent.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation +// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -52,11 +52,11 @@ public class PowerAccent : IDisposable }); })); - _keyboardListener.SetNextCharEvent(new PowerToys.PowerAccentKeyboardService.NextChar((TriggerKey triggerKey) => + _keyboardListener.SetNextCharEvent(new PowerToys.PowerAccentKeyboardService.NextChar((TriggerKey triggerKey, bool shiftPressed) => { System.Windows.Application.Current.Dispatcher.Invoke(() => { - ProcessNextChar(triggerKey); + ProcessNextChar(triggerKey, shiftPressed); }); })); @@ -106,7 +106,7 @@ public class PowerAccent : IDisposable _visible = false; } - private void ProcessNextChar(TriggerKey triggerKey) + private void ProcessNextChar(TriggerKey triggerKey, bool shiftPressed) { if (_visible && _selectedIndex == -1) { @@ -141,13 +141,27 @@ public class PowerAccent : IDisposable if (triggerKey == TriggerKey.Space) { - if (_selectedIndex < _characters.Length - 1) + if (shiftPressed) { - ++_selectedIndex; + if (_selectedIndex == 0) + { + _selectedIndex = _characters.Length - 1; + } + else + { + --_selectedIndex; + } } else { - _selectedIndex = 0; + if (_selectedIndex < _characters.Length - 1) + { + ++_selectedIndex; + } + else + { + _selectedIndex = 0; + } } } diff --git a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp index 232e5b9943..362f3733fc 100644 --- a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp +++ b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp @@ -1,4 +1,4 @@ -#include "pch.h" +#include "pch.h" #include "KeyboardListener.h" #include "KeyboardListener.g.cpp" @@ -12,7 +12,7 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation { KeyboardListener::KeyboardListener() : - m_toolbarVisible(false), m_triggeredWithSpace(false) + m_toolbarVisible(false), m_triggeredWithSpace(false), m_leftShiftPressed(false), m_rightShiftPressed(false) { s_instance = this; LoggerHelpers::init_logger(L"PowerAccent", L"PowerAccentKeyboardService", "PowerAccent"); @@ -66,8 +66,8 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation void KeyboardListener::SetNextCharEvent(NextChar nextCharEvent) { - m_nextCharCb = [trigger = std::move(nextCharEvent)](TriggerKey triggerKey) { - trigger(triggerKey); + m_nextCharCb = [trigger = std::move(nextCharEvent)](TriggerKey triggerKey, bool shiftPressed) { + trigger(triggerKey, shiftPressed); }; } @@ -144,6 +144,18 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation bool KeyboardListener::OnKeyDown(KBDLLHOOKSTRUCT info) noexcept { auto letterKey = static_cast(info.vkCode); + + // Shift key is detected only if the toolbar is already visible to avoid conflicts with uppercase + if (!m_leftShiftPressed && m_toolbarVisible && info.vkCode == VK_LSHIFT) + { + m_leftShiftPressed = true; + } + + if (!m_rightShiftPressed && m_toolbarVisible && info.vkCode == VK_RSHIFT) + { + m_rightShiftPressed = true; + } + if (std::find(letters.begin(), letters.end(), letterKey) != cend(letters) && m_isLanguageLetterCb(letterKey)) { m_stopwatch.reset(); @@ -183,17 +195,17 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation if (triggerPressed == VK_LEFT) { Logger::debug(L"Next toolbar position - left"); - m_nextCharCb(TriggerKey::Left); + m_nextCharCb(TriggerKey::Left, m_leftShiftPressed || m_rightShiftPressed); } else if (triggerPressed == VK_RIGHT) { Logger::debug(L"Next toolbar position - right"); - m_nextCharCb(TriggerKey::Right); + m_nextCharCb(TriggerKey::Right, m_leftShiftPressed || m_rightShiftPressed); } else if (triggerPressed == VK_SPACE) { Logger::debug(L"Next toolbar position - space"); - m_nextCharCb(TriggerKey::Space); + m_nextCharCb(TriggerKey::Space, m_leftShiftPressed || m_rightShiftPressed); } return true; @@ -204,6 +216,16 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation bool KeyboardListener::OnKeyUp(KBDLLHOOKSTRUCT info) noexcept { + if (m_leftShiftPressed && info.vkCode == VK_LSHIFT) + { + m_leftShiftPressed = false; + } + + if (m_rightShiftPressed && info.vkCode == VK_RSHIFT) + { + m_rightShiftPressed = false; + } + if (std::find(std::begin(letters), end(letters), static_cast(info.vkCode)) != end(letters) && m_isLanguageLetterCb(static_cast(info.vkCode))) { letterPressed = LetterKey::None; diff --git a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.h b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.h index 73e66611c7..c56f7c912a 100644 --- a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.h +++ b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.h @@ -52,10 +52,12 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation PowerAccentSettings m_settings; std::function m_showToolbarCb; std::function m_hideToolbarCb; - std::function m_nextCharCb; + std::function m_nextCharCb; std::function m_isLanguageLetterCb; bool m_triggeredWithSpace; spdlog::stopwatch m_stopwatch; + bool m_leftShiftPressed; + bool m_rightShiftPressed; std::mutex m_mutex_excluded_apps; std::pair m_prevForegrndAppExcl{ NULL, false }; diff --git a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.idl b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.idl index 4877dce395..9cf0e7cbe4 100644 --- a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.idl +++ b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.idl @@ -60,7 +60,7 @@ namespace PowerToys [version(1.0), uuid(37197089-5438-4479-af57-30ab3f3c8be4)] delegate void ShowToolbar(LetterKey key); [version(1.0), uuid(8eb79d6b-1826-424f-9fbc-af21ae19725e)] delegate void HideToolbar(InputType inputType); - [version(1.0), uuid(db72d45c-a5a2-446f-bdc1-506e9121764a)] delegate void NextChar(TriggerKey inputSpace); + [version(1.0), uuid(db72d45c-a5a2-446f-bdc1-506e9121764a)] delegate void NextChar(TriggerKey inputSpace, boolean shiftPressed); [version(1.0), uuid(20be2919-2b91-4313-b6e0-4c3484fe91ef)] delegate void IsLanguageLetter(LetterKey key, [out] boolean* result); [default_interface] runtimeclass KeyboardListener {