@@ -647,28 +647,43 @@ void McBopomofoEngine::activate(const fcitx::InputMethodEntry& entry,
647647
648648void McBopomofoEngine::reset (const fcitx::InputMethodEntry& /* unused*/ ,
649649 fcitx::InputContextEvent& event) {
650+ state_ = std::make_unique<InputStates::Empty>();
651+
652+ fcitx::InputContext* context = event.inputContext ();
653+ if (context == nullptr ) {
654+ return ;
655+ }
656+
657+ // Reset the UI.
658+ context->inputPanel ().reset ();
659+ context->updateUserInterface (fcitx::UserInterfaceComponent::InputPanel);
660+
661+ // Explicitly reset the preedit when it's focus-out or reset. Force-commit
662+ // any residue upon all other reset events. McBopomofo users expect residue
663+ // to be committed upon IME switch. It would be ideal if focus-out or reset
664+ // also force-commits, but unfortunately different apps handle those two
665+ // events differently. Gnome Terminal force-commits any residue by itself but
666+ // Chrome clears everything. Some apps (e.g. Firefox) even rely on an explicit
667+ // preedit for those events to be handled correctly. Given how this is beyond
668+ // our control, the approach here is likely the most sensible.
650669 if (event.type () == fcitx::EventType::InputContextFocusOut ||
651670 event.type () == fcitx::EventType::InputContextReset) {
652- // If this is a FocusOutEvent, we let fcitx5 do its own clean up, and so we
653- // just force the state machine to go back to the empty state. The
654- // FocusOutEvent will cause the preedit buffer to be force-committed anyway.
655- //
656- // Note: We don't want to call enterNewState() with EmptyIgnoringPrevious
657- // state because we don't want to clean the preedit ourselves (which would
658- // cause nothing to be force-committed as the focus is switched, and that
659- // would cause user to lose what they've entered). We don't want to call
660- // enterNewState() with Empty state, either, because that would trigger
661- // commit of existing preedit buffer, resulting in double commit of the same
662- // text.
663- state_ = std::make_unique<InputStates::Empty>();
664671 keyHandler_->reset ();
672+
673+ bool useClientPreedit =
674+ context->capabilityFlags ().test (fcitx::CapabilityFlag::Preedit);
675+ if (useClientPreedit) {
676+ context->inputPanel ().setClientPreedit (fcitx::Text{});
677+ } else {
678+ context->inputPanel ().setPreedit (fcitx::Text{});
679+ }
680+ context->inputPanel ().setAuxDown (fcitx::Text{});
681+ context->updatePreedit ();
665682 } else {
666- fcitx::InputContext* context = event.inputContext ();
667683 keyHandler_->handleForceCommitAndReset (
668684 [this , context](std::unique_ptr<InputState> next) {
669685 enterNewState (context, std::move (next));
670686 });
671- state_ = std::make_unique<InputStates::Empty>();
672687 }
673688}
674689
0 commit comments