From fb3b51c123bdd5a7f1ea1aba03af0b78b8147eee Mon Sep 17 00:00:00 2001 From: Miho1254 Date: Thu, 5 Mar 2026 11:19:01 +0700 Subject: [PATCH] fix: improve key buffering and state recovery to prevent dropped keys --- src/lotus-state.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- src/lotus-state.h | 5 +++-- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/lotus-state.cpp b/src/lotus-state.cpp index 0869507..6fa2054 100644 --- a/src/lotus-state.cpp +++ b/src/lotus-state.cpp @@ -559,7 +559,7 @@ namespace fcitx { } else { std::string keyUtf8Check = Key::keySymToUTF8(currentSym); if (!keyUtf8Check.empty() && buffered_keys_.size() < MAX_BUFFERED_KEYS) { - buffered_keys_.push_back(currentSym); + buffered_keys_.push_back({currentSym, keyEvent.rawKey().states()}); } keyEvent.filterAndAccept(); } @@ -641,9 +641,21 @@ namespace fcitx { auto commitAfterReplay = UniqueCPtr(EnginePullCommit(lotusEngine_.handle())); if (commitAfterReplay && commitAfterReplay.get()[0]) { + std::string commitStr = commitAfterReplay.get(); + std::string commonPrefix, deletedPart, addedPart; + compareAndSplitStrings(oldPreBuffer_, commitStr, commonPrefix, deletedPart, addedPart); + + if (!deletedPart.empty()) { + performReplacement(deletedPart, addedPart); + } else if (!addedPart.empty()) { + ic_->commitString(addedPart); + } + history_.clear(); ResetEngine(lotusEngine_.handle()); oldPreBuffer_.clear(); + + keyEvent.filterAndAccept(); return; } @@ -997,13 +1009,14 @@ namespace fcitx { auto keys = std::move(buffered_keys_); buffered_keys_.clear(); for (size_t i = 0; i < keys.size(); ++i) { - KeySym sym = keys[i]; + KeySym sym = static_cast(keys[i].sym); + uint32_t state = keys[i].state; std::string keyUtf8 = Key::keySymToUTF8(sym); if (keyUtf8.empty()) { continue; } - bool processed = EngineProcessKeyEvent(lotusEngine_.handle(), sym, 0); + bool processed = EngineProcessKeyEvent(lotusEngine_.handle(), sym, state); auto commitF = UniqueCPtr(EnginePullCommit(lotusEngine_.handle())); if (commitF && commitF.get()[0]) { @@ -1019,10 +1032,12 @@ namespace fcitx { } } performReplacement(deletedPart, addedPart); + history_.clear(); + ResetEngine(lotusEngine_.handle()); + oldPreBuffer_.clear(); return; } else if (!addedPart.empty()) { ic_->commitString(addedPart); - oldPreBuffer_ = commitStr; } history_.clear(); @@ -1043,6 +1058,26 @@ namespace fcitx { auto commitAfterReplay = UniqueCPtr(EnginePullCommit(lotusEngine_.handle())); if (commitAfterReplay && commitAfterReplay.get()[0]) { + std::string commitStr = commitAfterReplay.get(); + std::string commonPrefix, deletedPart, addedPart; + compareAndSplitStrings(oldPreBuffer_, commitStr, commonPrefix, deletedPart, addedPart); + + if (!deletedPart.empty()) { + // Re-buffer remaining keys for next replay cycle. + for (size_t j = i + 1; j < keys.size(); ++j) { + if (buffered_keys_.size() < MAX_BUFFERED_KEYS) { + buffered_keys_.push_back(keys[j]); + } + } + performReplacement(deletedPart, addedPart); + history_.clear(); + ResetEngine(lotusEngine_.handle()); + oldPreBuffer_.clear(); + return; + } else if (!addedPart.empty()) { + ic_->commitString(addedPart); + } + history_.clear(); ResetEngine(lotusEngine_.handle()); oldPreBuffer_.clear(); diff --git a/src/lotus-state.h b/src/lotus-state.h index 63c834e..6e87ecc 100644 --- a/src/lotus-state.h +++ b/src/lotus-state.h @@ -17,6 +17,7 @@ #include "lotus.h" #include "emoji.h" +#include "lotus-utils.h" #include #include #include @@ -199,7 +200,7 @@ namespace fcitx { friend class LotusEngine; private: - static constexpr size_t MAX_BUFFERED_KEYS = 10; + static constexpr size_t MAX_BUFFERED_KEYS = 50; LotusEngine* engine_; InputContext* ic_; @@ -213,7 +214,7 @@ namespace fcitx { std::string emojiBuffer_; std::vector emojiCandidates_; bool waitAck_ = false; - std::vector buffered_keys_; ///< Keystrokes buffered during replacement + std::vector buffered_keys_; ///< Keystrokes buffered during replacement }; } // namespace fcitx