Files
msime-windows/server/tests/src/test_candidate_translation_policy.cpp
T
fanlusky a898c3b11c feat(candidate): Ctrl+Enter 上屏候选右侧的译文
候选框开着且高亮候选带译文时,Ctrl+Enter 上屏那条译文而不是候选本身。
译文只有一条就直接上屏;有多条时把候选框整个换成这几条译义,空格/数字键
照常选一条上屏。

TSF 端原先在分类器最前面把所有 Ctrl 组合都还给应用,Ctrl+Enter 到不了
Server。现在在那条拦截之前先判一次:候选框开着才认,否则组合仍归应用。
认下来的键走既有的 FUNCTION_SERVER_CANDIDATE_KEY 通道,由 Server 决定
是上屏(CommitExactText)还是只开一个新候选页(NavigationIgnored)。

译文页复用同一份 candidate_ui.items,因此云/AI/英文/emoji/颜文字这些异步
回调和候选扩展都要在这个子模式下让路,否则会把译文冲掉。输入串全程没动,
退出时把存下来的 items 和页码原样放回去即可。译文页上的空格/数字键只回
Normal / OutofRange——SELECT_BY_NUMBER 的 TSF 路径只认这两种。
2026-09-17 20:21:56 +08:00

53 lines
2.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "ipc/candidate_translation_policy.h"
#include "tests/includes/test_framework.h"
TEST_CASE(ctrl_enter_alone_commits_the_secondary_candidate)
{
using FanyImeIpc::IsTranslationCommitKey;
REQUIRE(IsTranslationCommitKey(0x0D, FanyImeIpc::kModifierControl));
// The UI-less flag lives outside the modifier mask and must not disarm the shortcut.
REQUIRE(IsTranslationCommitKey(0x0D, FanyImeIpc::kModifierControl | FanyImeIpc::kModifierUiLess));
REQUIRE(!IsTranslationCommitKey(0x0D, 0));
REQUIRE(!IsTranslationCommitKey(0x0D, FanyImeIpc::kModifierControl | FanyImeIpc::kModifierShift));
REQUIRE(!IsTranslationCommitKey(0x0D, FanyImeIpc::kModifierControl | FanyImeIpc::kModifierAlt));
REQUIRE(!IsTranslationCommitKey(0x20, FanyImeIpc::kModifierControl));
REQUIRE(!IsTranslationCommitKey('J', FanyImeIpc::kModifierControl));
}
TEST_CASE(translation_gloss_splits_on_both_semicolon_widths)
{
using FanyImeIpc::SplitTranslationGloss;
// en->zh glosses join senses with the fullwidth semicolon.
const auto apple = SplitTranslationGloss("苹果;家伙;[计]苹果公司");
REQUIRE_EQ(apple.size(), static_cast<size_t>(3));
REQUIRE_EQ(apple[0], std::string("苹果"));
REQUIRE_EQ(apple[1], std::string("家伙"));
REQUIRE_EQ(apple[2], std::string("[计]苹果公司"));
// zh->en glosses use "; " and the trailing space must not survive.
const auto chuan = SplitTranslationGloss("string; trail; chuan");
REQUIRE_EQ(chuan.size(), static_cast<size_t>(3));
REQUIRE_EQ(chuan[0], std::string("string"));
REQUIRE_EQ(chuan[1], std::string("trail"));
REQUIRE_EQ(chuan[2], std::string("chuan"));
}
TEST_CASE(translation_gloss_keeps_a_single_sense_whole)
{
using FanyImeIpc::SplitTranslationGloss;
// A cloud gloss is one sentence: commas inside it are not sense separators.
const auto cloud = SplitTranslationGloss("今天天气不错,我们出去走走");
REQUIRE_EQ(cloud.size(), static_cast<size_t>(1));
REQUIRE_EQ(cloud[0], std::string("今天天气不错,我们出去走走"));
REQUIRE(SplitTranslationGloss("").empty());
REQUIRE(SplitTranslationGloss(" ").empty());
// Empty senses are dropped rather than becoming blank candidates.
REQUIRE_EQ(SplitTranslationGloss(";;").size(), static_cast<size_t>(0));
const auto ragged = SplitTranslationGloss(";apple; ;pear;");
REQUIRE_EQ(ragged.size(), static_cast<size_t>(2));
REQUIRE_EQ(ragged[0], std::string("apple"));
REQUIRE_EQ(ragged[1], std::string("pear"));
}