Skip to content

通过 switcher 切换 option state 后,无法获取 option state 对应的值 #918

@imfuxiao

Description

@imfuxiao

Describe the bug

比如 F4 进入 Switcher 后,切换 option 状态(非 schema),如 ascii_mode 的状态,切换成功后,比如在 notification_handler 获取到切换状态通知后,在获取 option 对的值 rime->get_state_label(session_id, option_name, state) 是无法获取的。

相反,如果不通过 Switcher 切换,直接通过 rime->set_option(session_id, option, is_on) 切换 option,同样在 notification_handler 获取到切换状态通知后,在获取 option 对的值 rime->get_state_label(session_id, option_name, state) 是可以获取到的。

To Reproduce
Steps to reproduce the bug:

  1. F4 进入 Swicher 模式
  2. 根据菜单选项切换 option,比如切换 ascii_mode
  3. 在 notification_handler 中获取 option state 对应的值。如rime->get_state_label(session_id, option_name, state) 得到的值是空值。

Expected behavior
期望通过 switcher 切换 option 与 通过 rime->set_option() api 切换 option 后,都可以正常获取到 option 对应的值。

Additional context

查阅代码,得知

  1. 键入 F4 进入 Switcher 后,Switcher 会激活 active_engine
// switcher.cc 

...
ProcessResult Switcher::ProcessKeyEvent(const KeyEvent& key_event) {
  for (const KeyEvent& hotkey : hotkeys_) {
    if (key_event == hotkey) {
      if (!active_ && engine_) {
        Activate();
...
void Switcher::Activate() {
  LOG(INFO) << "switcher is activated.";
  context_->set_option("_fold_options", fold_options_);
  RefreshMenu();
  engine_->set_active_engine(this); // 设置 `active_engine`
  active_ = true;
}
...
  1. 而获取 option 对应值的代码 RimeGetStateLabelAbbreviated() 会使用 active_engine
// rime_api_impl.h

static RimeStringSlice RimeGetStateLabelAbbreviated(RimeSessionId session_id,
                                                    const char* option_name,
                                                    Bool state,
                                                    Bool abbreviated) {
  an<Session> session(Service::instance().GetSession(session_id));
  if (!session)
    return {nullptr, 0};
  Config* config = session->schema()->config(); // 这里会获取 `active_engine`
  if (!config)
    return {nullptr, 0};
  Switches switches(config);
  StringSlice label = switches.GetStateLabel(option_name, state, abbreviated);
  return {label.str, label.length};
}

//  service.cc 

Schema* Session::schema() const {
  return engine_ ? engine_->active_engine()->schema() : NULL; // 这里会获取 `active_engine`
}
  1. 而 Swticher 中 active_engine 获取到的 schema 不是当前正在使用的 schema,而是 default 的配置,从而导致获取 option 选项的值为空。而通过 rime->set_option() 设置,engine_->active_engine()->schema() 获取到的 schema 是正在使用的 schema,所以可以正常拿到 option 的值。
image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions