Add default IME language and per-app/global CN-EN scope settings.
Wire config + settings UI for default_ime_mode / ime_mode_scope, and sync unified mode across apps when scope is global.
This commit is contained in:
1 parent
71fa7dddeb
commit
6632e9ebcf
6 files changed
+151
-2
No files matched your search
@@ -92,6 +92,10 @@ tsf_preedit_style = "raw"
|
||||
#
|
||||
[input]
|
||||
character_set = "simplified" # 候选输出字形,可选:"simplified", "traditional"
|
||||
# 启动/从其他输入法切换到本输入法时的默认中英文,可选:"chinese", "english"
|
||||
default_ime_mode = "chinese"
|
||||
# 中英文状态范围,可选:"app"(按应用分别记忆), "global"(所有应用保持统一)
|
||||
ime_mode_scope = "app"
|
||||
# 组合说明:
|
||||
# legacy + shuangpin -> 使用旧版双拼会话实现(当前最稳定)
|
||||
# legacy + quanpin -> 自动切换为新版引擎全拼会话
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace
|
||||
std::string g_session_backend = "legacy";
|
||||
SchemeType g_input_scheme = SchemeType::Shuangpin;
|
||||
std::string g_character_set = "simplified";
|
||||
std::string g_default_ime_mode = "chinese";
|
||||
std::string g_ime_mode_scope = "app";
|
||||
int g_candidate_page_size = 8;
|
||||
std::string g_candidate_font = "Noto Sans SC";
|
||||
std::string g_candidate_english_font = "Segoe UI";
|
||||
@@ -282,6 +284,16 @@ bool LoadImeConfig()
|
||||
const std::string character_set =
|
||||
tbl["input"]["character_set"].value_or(std::string("simplified"));
|
||||
g_character_set = character_set == "traditional" ? "traditional" : "simplified";
|
||||
{
|
||||
const std::string mode =
|
||||
tbl["input"]["default_ime_mode"].value_or(std::string("chinese"));
|
||||
g_default_ime_mode = mode == "english" ? "english" : "chinese";
|
||||
}
|
||||
{
|
||||
const std::string scope =
|
||||
tbl["input"]["ime_mode_scope"].value_or(std::string("app"));
|
||||
g_ime_mode_scope = scope == "global" ? "global" : "app";
|
||||
}
|
||||
g_shuangpin_schema = tbl["input"]["shuangpin_schema"].value_or(std::string("xiaohe"));
|
||||
g_wubi_schema = tbl["input"]["wubi_schema"].value_or(std::string("wubi86"));
|
||||
g_shuangpin_preedit_mode = tbl["input"]["shuangpin_preedit_mode"].value_or(std::string("quanpin"));
|
||||
@@ -751,6 +763,49 @@ bool SetConfiguredCharacterSet(const std::string &character_set)
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &GetConfiguredDefaultImeMode()
|
||||
{
|
||||
return g_default_ime_mode;
|
||||
}
|
||||
|
||||
bool SetConfiguredDefaultImeMode(const std::string &mode)
|
||||
{
|
||||
if (mode != "chinese" && mode != "english")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!WriteConfiguredValue("input", "default_ime_mode", EscapeTomlBasicString(mode)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_default_ime_mode = mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &GetConfiguredImeModeScope()
|
||||
{
|
||||
return g_ime_mode_scope;
|
||||
}
|
||||
|
||||
bool SetConfiguredImeModeScope(const std::string &scope)
|
||||
{
|
||||
if (scope != "app" && scope != "global")
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!WriteConfiguredValue("input", "ime_mode_scope", EscapeTomlBasicString(scope)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
g_ime_mode_scope = scope;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsConfiguredImeModeScopeGlobal()
|
||||
{
|
||||
return g_ime_mode_scope == "global";
|
||||
}
|
||||
|
||||
const std::string &GetConfiguredShuangpinSchema()
|
||||
{
|
||||
return g_shuangpin_schema;
|
||||
|
||||
@@ -81,6 +81,13 @@ std::string GetConfiguredInputSchemeName();
|
||||
bool SetConfiguredInputScheme(const std::string &scheme);
|
||||
const std::string &GetConfiguredCharacterSet();
|
||||
bool SetConfiguredCharacterSet(const std::string &character_set);
|
||||
// "chinese" | "english" — default CN/EN when activating this IME.
|
||||
const std::string &GetConfiguredDefaultImeMode();
|
||||
bool SetConfiguredDefaultImeMode(const std::string &mode);
|
||||
// "app" | "global" — per-app memory vs unified CN/EN across apps.
|
||||
const std::string &GetConfiguredImeModeScope();
|
||||
bool SetConfiguredImeModeScope(const std::string &scope);
|
||||
bool IsConfiguredImeModeScopeGlobal();
|
||||
const std::string &GetConfiguredShuangpinSchema();
|
||||
bool SetConfiguredShuangpinSchema(const std::string &schema);
|
||||
const std::string &GetConfiguredWubiSchema();
|
||||
|
||||
@@ -146,6 +146,13 @@ AsyncRequestOrigin g_ai_request_origin;
|
||||
std::string g_ai_context;
|
||||
std::mutex g_status_snapshot_mutex;
|
||||
int g_latest_status_snapshot = -1;
|
||||
// Global CN/EN authority for input.ime_mode_scope = "global".
|
||||
// -1 until first StatusSnapshot or lazy seed from default_ime_mode.
|
||||
int g_authoritative_cn_mode = -1;
|
||||
uint64_t g_last_status_snapshot_client_id = 0;
|
||||
// After switching away from this IME, the next StatusSnapshot must restore the
|
||||
// global mode even when the same process/thread client_id reconnects.
|
||||
bool g_force_global_ime_sync = false;
|
||||
HWND g_status_snapshot_window = nullptr;
|
||||
std::mutex g_candidate_ui_owner_mutex;
|
||||
FanyImeIpc::CandidateUiOwnerState g_candidate_ui_owner;
|
||||
@@ -184,6 +191,16 @@ void PublishStatusSnapshotValue(int packed_state)
|
||||
}
|
||||
}
|
||||
|
||||
int EnsureAuthoritativeCnMode()
|
||||
{
|
||||
if (g_authoritative_cn_mode < 0)
|
||||
{
|
||||
ReloadImeConfigIfChanged();
|
||||
g_authoritative_cn_mode = GetConfiguredDefaultImeMode() == "english" ? 0 : 1;
|
||||
}
|
||||
return g_authoritative_cn_mode;
|
||||
}
|
||||
|
||||
void UpdateCloudInput(const std::string &input, uint64_t client_id = 0, uint64_t activation_epoch = 0)
|
||||
{
|
||||
std::lock_guard lock(g_async_request_mutex);
|
||||
@@ -944,6 +961,7 @@ void WorkerThread()
|
||||
case TaskType::ClientDeactivated: {
|
||||
// Unlike a route-only suspension, terminal TIP deactivation means
|
||||
// the user switched to another input method.
|
||||
g_force_global_ime_sync = true;
|
||||
PostMessage(::global_hwnd, WM_IMEDEACTIVATE, 0, 0);
|
||||
PostMessage(::global_hwnd, WM_HIDE_MAIN_WINDOW, 0, 0);
|
||||
ClearState();
|
||||
@@ -960,11 +978,52 @@ void WorkerThread()
|
||||
}
|
||||
|
||||
case TaskType::StatusSnapshot: {
|
||||
ReloadImeConfigIfChanged();
|
||||
const int cn_state = task.pipe_data.keycode != 0 ? 1 : 0;
|
||||
const int fullwidth_state = task.pipe_data.modifiers_down != 0 ? 1 : 0;
|
||||
const int punctuation_state = task.pipe_data.pinyin_length != 0 ? 1 : 0;
|
||||
const int packed_state = (cn_state << 2) | (fullwidth_state << 1) | punctuation_state;
|
||||
if (FanyImeIpc::ShouldResetCompositionForImeMode(cn_state != 0))
|
||||
int effective_cn = cn_state;
|
||||
const bool force_global_sync = g_force_global_ime_sync;
|
||||
g_force_global_ime_sync = false;
|
||||
|
||||
if (IsConfiguredImeModeScopeGlobal())
|
||||
{
|
||||
const int authoritative = EnsureAuthoritativeCnMode();
|
||||
const bool client_changed =
|
||||
g_last_status_snapshot_client_id != 0 && task.client_id != g_last_status_snapshot_client_id;
|
||||
if (client_changed || force_global_sync)
|
||||
{
|
||||
// Focus moved to another app, or switched back to this IME:
|
||||
// keep the unified mode.
|
||||
effective_cn = authoritative;
|
||||
if (cn_state != authoritative && task.client_id != 0)
|
||||
{
|
||||
SendToTsfWorkerThreadClientViaNamedpipe(
|
||||
task.client_id, task.activation_epoch,
|
||||
authoritative != 0 ? Global::DataFromServerMsgTypeToTsfWorkerThread::SwitchToCn
|
||||
: Global::DataFromServerMsgTypeToTsfWorkerThread::SwitchToEn,
|
||||
L"");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Same client (or first report): accept as the new authority.
|
||||
g_authoritative_cn_mode = cn_state;
|
||||
effective_cn = cn_state;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_authoritative_cn_mode = cn_state;
|
||||
}
|
||||
|
||||
if (task.client_id != 0)
|
||||
{
|
||||
g_last_status_snapshot_client_id = task.client_id;
|
||||
}
|
||||
|
||||
const int packed_state = (effective_cn << 2) | (fullwidth_state << 1) | punctuation_state;
|
||||
if (FanyImeIpc::ShouldResetCompositionForImeMode(effective_cn != 0))
|
||||
{
|
||||
PostMessage(::global_hwnd, WM_HIDE_MAIN_WINDOW, 0, 0);
|
||||
ClearState();
|
||||
|
||||
@@ -216,6 +216,8 @@ void PostConfig()
|
||||
{{"input",
|
||||
{{"schema", GetConfiguredInputSchemeName()},
|
||||
{"character_set", GetConfiguredCharacterSet()},
|
||||
{"default_ime_mode", GetConfiguredDefaultImeMode()},
|
||||
{"ime_mode_scope", GetConfiguredImeModeScope()},
|
||||
{"shuangpin_schema", GetConfiguredShuangpinSchema()},
|
||||
{"wubi_schema", GetConfiguredWubiSchema()}}},
|
||||
{"general",
|
||||
@@ -306,6 +308,10 @@ bool ApplyConfigUpdate(const json::object &data)
|
||||
return SetConfiguredInputScheme(json::value_to<std::string>(data.at("value")));
|
||||
if (path == "input.character_set")
|
||||
return SetConfiguredCharacterSet(json::value_to<std::string>(data.at("value")));
|
||||
if (path == "input.default_ime_mode")
|
||||
return SetConfiguredDefaultImeMode(json::value_to<std::string>(data.at("value")));
|
||||
if (path == "input.ime_mode_scope")
|
||||
return SetConfiguredImeModeScope(json::value_to<std::string>(data.at("value")));
|
||||
if (path == "input.shuangpin_schema")
|
||||
return SetConfiguredShuangpinSchema(json::value_to<std::string>(data.at("value")));
|
||||
if (path == "input.wubi_schema")
|
||||
|
||||
@@ -1662,6 +1662,22 @@ HRESULT OnControllerCreatedSettingsWnd( //
|
||||
PostSettingsConfig();
|
||||
}
|
||||
}
|
||||
else if (path == "input.default_ime_mode")
|
||||
{
|
||||
const std::string value = json::value_to<std::string>(data.at("value"));
|
||||
if (SetConfiguredDefaultImeMode(value))
|
||||
{
|
||||
PostSettingsConfig();
|
||||
}
|
||||
}
|
||||
else if (path == "input.ime_mode_scope")
|
||||
{
|
||||
const std::string value = json::value_to<std::string>(data.at("value"));
|
||||
if (SetConfiguredImeModeScope(value))
|
||||
{
|
||||
PostSettingsConfig();
|
||||
}
|
||||
}
|
||||
else if (path == "input.shuangpin_schema")
|
||||
{
|
||||
const std::string value = json::value_to<std::string>(data.at("value"));
|
||||
@@ -2087,6 +2103,8 @@ void PostSettingsConfig()
|
||||
{"type", "configSnapshot"},
|
||||
{"data", {{"input", {{"schema", GetConfiguredInputSchemeName()},
|
||||
{"character_set", GetConfiguredCharacterSet()},
|
||||
{"default_ime_mode", GetConfiguredDefaultImeMode()},
|
||||
{"ime_mode_scope", GetConfiguredImeModeScope()},
|
||||
{"shuangpin_schema", GetConfiguredShuangpinSchema()},
|
||||
{"wubi_schema", GetConfiguredWubiSchema()}}},
|
||||
{"general", {{"floating_toolbar", GetConfiguredFloatingToolbarEnabled()},
|
||||
|
||||
Reference in new issue
Block a user