Merge pull request #642 from Ehtasham-Yasin/feat/shuangpin-shift-enter
feat(server): submit converted Shuangpin with Shift+Enter
This commit is contained in:
6 files changed
+71
-6
No files matched your search
@@ -905,7 +905,13 @@ void HandleImeKey(uint64_t client_id, uint64_t activation_epoch, uint64_t reques
|
||||
const bool shift_only = (Global::ModifiersDown & 0b00000111u) == 0b00000001u;
|
||||
const bool chinese_scheme = g_inputSession && (g_inputSession->current_scheme_type() == SchemeType::Quanpin ||
|
||||
g_inputSession->current_scheme_type() == SchemeType::Shuangpin);
|
||||
if (Global::Keycode == VK_RETURN && !input_before_key.empty() && GetConfiguredEnterLearnsEnglishWord())
|
||||
const bool pinyin_commit =
|
||||
FanyImeIpc::IsPinyinCommitKey(Global::Keycode, Global::ModifiersDown) && !input_before_key.empty();
|
||||
const bool convert_shuangpin = pinyin_commit && g_inputSession->current_scheme_type() == SchemeType::Shuangpin &&
|
||||
!g_english_input_mode && !g_r_mode_triggered &&
|
||||
!IsSpecialModeCompositionActive(input_before_key);
|
||||
if (Global::Keycode == VK_RETURN && !input_before_key.empty() && !convert_shuangpin &&
|
||||
GetConfiguredEnterLearnsEnglishWord())
|
||||
{
|
||||
std::string english_word;
|
||||
// V 模式没有触发标记,按输入串认:回车上屏的 V123 不是要学的英文词。
|
||||
@@ -916,6 +922,16 @@ void HandleImeKey(uint64_t client_id, uint64_t activation_epoch, uint64_t reques
|
||||
english_word = g_r_mode_triggered ? "R" + input_before_key : input_before_key;
|
||||
EnqueueLearnEnteredEnglishWordTask(english_word);
|
||||
}
|
||||
if (pinyin_commit)
|
||||
{
|
||||
const std::string raw = g_r_mode_triggered ? "R" + input_before_key : input_before_key;
|
||||
const std::string text = FanyImeIpc::EnteredPinyinText(
|
||||
raw, convert_shuangpin ? g_inputSession->get_quanpin() : std::string{}, convert_shuangpin);
|
||||
Global::candidate_ui.selected_text = string_to_wstring(GlobalIme::composition.creating_word.word + text);
|
||||
Global::MsgTypeToTsf = Global::DataFromServerMsgType::CommitExactText;
|
||||
SendCurrentDataToClient(client_id, activation_epoch, request_id);
|
||||
return;
|
||||
}
|
||||
if (chinese_scheme && !g_english_input_mode && GetConfiguredQuickPhraseEnabled() && input_before_key.empty() &&
|
||||
Global::Keycode == 'K' && Global::Wch == L'K' && shift_only)
|
||||
g_quick_phrase_triggered = true;
|
||||
|
||||
@@ -30,6 +30,19 @@ constexpr bool IsEnglishModeToggleKey(uint32_t keycode, uint32_t modifiers_down)
|
||||
return keycode == static_cast<uint32_t>('E') && (modifiers_down & kKeyModifierMask) == kEnglishModeToggleModifiers;
|
||||
}
|
||||
|
||||
constexpr bool IsPinyinCommitKey(uint32_t keycode, uint32_t modifiers_down)
|
||||
{
|
||||
return keycode == 0x0D && (modifiers_down & kKeyModifierMask) == kModifierShift;
|
||||
}
|
||||
|
||||
inline std::string EnteredPinyinText(const std::string &raw, std::string quanpin, bool convert_shuangpin)
|
||||
{
|
||||
if (!convert_shuangpin || quanpin.empty())
|
||||
return raw;
|
||||
quanpin.erase(std::remove(quanpin.begin(), quanpin.end(), '\''), quanpin.end());
|
||||
return quanpin;
|
||||
}
|
||||
|
||||
// Return -1 / +1 for the first / last Han character, or zero for an ordinary key.
|
||||
constexpr int WordToCharacterDirection(uint32_t keycode, uint32_t character, uint32_t modifiers, bool enabled,
|
||||
bool minus_equal)
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
#include "ipc/input_key_policy.h"
|
||||
#include "tests/includes/test_framework.h"
|
||||
|
||||
TEST_CASE(pinyin_commit_requires_shift_enter)
|
||||
{
|
||||
REQUIRE(FanyImeIpc::IsPinyinCommitKey(0x0D, 1));
|
||||
REQUIRE(FanyImeIpc::IsPinyinCommitKey(0x0D, 1 | FanyImeIpc::kModifierUiLess));
|
||||
for (unsigned modifiers = 0; modifiers < 8; ++modifiers)
|
||||
REQUIRE(FanyImeIpc::IsPinyinCommitKey(0x0D, modifiers) == (modifiers == 1));
|
||||
REQUIRE(!FanyImeIpc::IsPinyinCommitKey('A', 1));
|
||||
}
|
||||
|
||||
TEST_CASE(pinyin_commit_converts_shuangpin_and_preserves_raw_fallback)
|
||||
{
|
||||
using FanyImeIpc::EnteredPinyinText;
|
||||
REQUIRE_EQ(EnteredPinyinText("nihc", "ni'hao", true), std::string("nihao"));
|
||||
REQUIRE_EQ(EnteredPinyinText("ni'hc", "ni'hao'", true), std::string("nihao"));
|
||||
REQUIRE_EQ(EnteredPinyinText("vgh", "zheng'h", true), std::string("zhengh"));
|
||||
REQUIRE_EQ(EnteredPinyinText("nihc", "ni'hao", false), std::string("nihc"));
|
||||
REQUIRE_EQ(EnteredPinyinText("hello", "", true), std::string("hello"));
|
||||
REQUIRE_EQ(EnteredPinyinText("U4E00", "", false), std::string("U4E00"));
|
||||
REQUIRE_EQ(EnteredPinyinText("", "", true), std::string(""));
|
||||
}
|
||||
|
||||
TEST_CASE(word_to_character_uses_only_the_selected_unmodified_key_pair)
|
||||
{
|
||||
using FanyImeIpc::WordToCharacterDirection;
|
||||
|
||||
@@ -141,6 +141,12 @@ bool IsTranslationCommitShortcut(UINT code, UINT modifiers)
|
||||
(GetAsyncKeyState(VK_RWIN) & 0x8000) == 0;
|
||||
}
|
||||
|
||||
bool IsPinyinCommitShortcut(UINT code, UINT modifiers)
|
||||
{
|
||||
return code == VK_RETURN && (modifiers & 0b00000111u) == 0b00000001u && (GetAsyncKeyState(VK_LWIN) & 0x8000) == 0 &&
|
||||
(GetAsyncKeyState(VK_RWIN) & 0x8000) == 0;
|
||||
}
|
||||
|
||||
bool IsCharacterSetInputModeToggle(UINT code, UINT modifiers)
|
||||
{
|
||||
return FanyImeProtocol::IsCharacterSetShortcut(code, modifiers) && (GetAsyncKeyState(VK_LWIN) & 0x8000) == 0 &&
|
||||
@@ -333,9 +339,12 @@ BOOL CMetasequoiaIME::_IsKeyEaten( //
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// 候选框开着的时候 Ctrl+Enter 上屏高亮候选的译文;没有候选框时它仍然属于应用。
|
||||
if (!freshCompositionState && _candidateMode != CANDIDATE_NONE &&
|
||||
IsTranslationCommitShortcut(*pCodeOut, shortcutModifiers))
|
||||
// Ctrl+Enter commits a candidate translation. Shift+Enter commits the
|
||||
// Server's converted spelling, including compositions without candidates.
|
||||
if (!freshCompositionState &&
|
||||
((_candidateMode != CANDIDATE_NONE && IsTranslationCommitShortcut(*pCodeOut, shortcutModifiers)) ||
|
||||
(!_serverUnavailableFallbackActive && pCompositionProcessorEngine->GetVirtualKeyLength() > 0 &&
|
||||
IsPinyinCommitShortcut(*pCodeOut, shortcutModifiers))))
|
||||
{
|
||||
if (pKeyState)
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ KEYSTROKE_FUNCTION SegmentEditFunction(UINT code, UINT modifiers);
|
||||
UINT CaptureIpcModifiers();
|
||||
bool IsEnglishInputModeToggle(UINT code, UINT modifiers);
|
||||
bool IsTranslationCommitShortcut(UINT code, UINT modifiers);
|
||||
bool IsPinyinCommitShortcut(UINT code, UINT modifiers);
|
||||
bool IsCharacterSetInputModeToggle(UINT code, UINT modifiers);
|
||||
void PostOwnerMessageWithSyncFallback(HWND window, UINT message, WPARAM wParam = 0, LPARAM lParam = 0);
|
||||
bool IsShiftVk(UINT code);
|
||||
|
||||
@@ -418,8 +418,13 @@ bool CMetasequoiaIME::_ClassifyDeferredKeyDown(_In_ ITfContext *pContext, WPARAM
|
||||
// 同上:译文上屏也要在这条 Ctrl/Alt 拦截之前分类,否则这颗键会被交还给应用。
|
||||
const bool projectedCandidateActive =
|
||||
_deferredKeyProjectionValid ? _deferredProjectedCandidateActive : (_candidateMode == CANDIDATE_ORIGINAL);
|
||||
if (projectedImeOpen && !_IsKeyboardDisabled() && projectedCandidateActive &&
|
||||
IsTranslationCommitShortcut(*classifiedCode, capturedModifiers))
|
||||
const bool projectedInputActive = _deferredKeyProjectionValid
|
||||
? _deferredProjectedInputLength > 0
|
||||
: _pCompositionProcessorEngine->GetVirtualKeyLength() > 0;
|
||||
if (projectedImeOpen && !_IsKeyboardDisabled() &&
|
||||
((projectedCandidateActive && IsTranslationCommitShortcut(*classifiedCode, capturedModifiers)) ||
|
||||
(!_serverUnavailableFallbackActive && projectedInputActive &&
|
||||
IsPinyinCommitShortcut(*classifiedCode, capturedModifiers))))
|
||||
{
|
||||
keyState->Category = CATEGORY_CANDIDATE;
|
||||
keyState->Function = FUNCTION_SERVER_CANDIDATE_KEY;
|
||||
|
||||
Reference in new issue
Block a user