1616#include < fcitx-config/iniparser.h>
1717#include < fcitx-config/rawconfig.h>
1818#include < fcitx-utils/event.h>
19+ #include < fcitx-utils/eventloopinterface.h>
1920#include < fcitx-utils/fs.h>
2021#include < fcitx-utils/i18n.h>
2122#include < fcitx-utils/log.h>
@@ -53,6 +54,9 @@ namespace fcitx::rime {
5354
5455namespace {
5556
57+ // Allow notification for 60secs.
58+ constexpr uint64_t NotificationTimeout = 60000000 ;
59+
5660std::unordered_map<std::string, std::unordered_map<std::string, bool >>
5761parseAppOptions (rime_api_t *api, RimeConfig *config) {
5862 std::unordered_map<std::string, std::unordered_map<std::string, bool >>
@@ -210,7 +214,7 @@ RimeEngine::RimeEngine(Instance *instance)
210214 syncAction_.setShortText (_ (" Synchronize" ));
211215
212216 syncAction_.connect <SimpleAction::Activated>([this ](InputContext *ic) {
213- sync ();
217+ sync (/* userTriggered= */ true );
214218 auto *state = this ->state (ic);
215219 if (state && ic->hasFocus ()) {
216220 state->updateUI (ic, false );
@@ -224,6 +228,8 @@ RimeEngine::RimeEngine(Instance *instance)
224228 globalConfigReloadHandle_ = instance_->watchEvent (
225229 EventType::GlobalConfigReloaded, EventWatcherPhase::Default,
226230 [this ](Event &) { refreshSessionPoolPolicy (); });
231+
232+ allowNotification (" failure" );
227233 reloadConfig ();
228234 constructed_ = true ;
229235}
@@ -335,7 +341,7 @@ void RimeEngine::setSubConfig(const std::string &path,
335341 if (path == " deploy" ) {
336342 deploy ();
337343 } else if (path == " sync" ) {
338- sync ();
344+ sync (/* userTriggered= */ true );
339345 }
340346}
341347
@@ -504,7 +510,6 @@ void RimeEngine::deactivate(const InputMethodEntry &entry,
504510
505511void RimeEngine::keyEvent (const InputMethodEntry &entry, KeyEvent &event) {
506512 FCITX_UNUSED (entry);
507- lastKeyEventTime_ = now (CLOCK_MONOTONIC);
508513 RIME_DEBUG () << " Rime receive key: " << event.rawKey () << " "
509514 << event.isRelease ();
510515 auto *inputContext = event.inputContext ();
@@ -513,7 +518,7 @@ void RimeEngine::keyEvent(const InputMethodEntry &entry, KeyEvent &event) {
513518 deploy ();
514519 return event.filterAndAccept ();
515520 } else if (event.key ().checkKeyList (*config_.synchronize )) {
516- sync ();
521+ sync (/* userTriggered= */ true );
517522 return event.filterAndAccept ();
518523 }
519524 }
@@ -534,15 +539,12 @@ void RimeEngine::reset(const InputMethodEntry & /*entry*/,
534539 inputContext->updateUserInterface (UserInterfaceComponent::InputPanel);
535540}
536541
537- void RimeEngine::blockNotificationFor (uint64_t usec) {
538- blockNotificationBefore_ = now (CLOCK_MONOTONIC) + usec;
542+ void RimeEngine::allowNotification (std::string type) {
543+ allowNotificationUntil_ = now (CLOCK_MONOTONIC) + NotificationTimeout;
544+ allowNotificationType_ = std::move (type);
539545}
540546
541- void RimeEngine::save () {
542- // Block notification for 5 sec.
543- blockNotificationFor (5000000 );
544- sync ();
545- }
547+ void RimeEngine::save () { sync (/* userTriggered=*/ false ); }
546548
547549void RimeEngine::rimeNotificationHandler (void *context, RimeSessionId session,
548550 const char *messageType,
@@ -578,7 +580,7 @@ void RimeEngine::notify(RimeSessionId session, const std::string &messageType,
578580 const char *message = nullptr ;
579581 const char *icon = " " ;
580582 const char *tipId = " " ;
581- int timeout = 3000 ;
583+ const int timeout = 3000 ;
582584 bool blockMessage = false ;
583585 if (messageType == " deploy" ) {
584586 tipId = " fcitx-rime-deploy" ;
@@ -612,14 +614,17 @@ void RimeEngine::notify(RimeSessionId session, const std::string &messageType,
612614 }
613615
614616 auto *notifications = this ->notifications ();
615- if (message && notifications &&
616- now (CLOCK_MONOTONIC) > blockNotificationBefore_) {
617+ const auto current = now (CLOCK_MONOTONIC);
618+ if (message && notifications && current > silenceNotificationUntil_ &&
619+ (current < allowNotificationUntil_ &&
620+ (allowNotificationType_.empty () ||
621+ messageType == allowNotificationType_))) {
617622 notifications->call <INotifications::showTip>(
618623 tipId, _ (" Rime" ), icon, _ (" Rime" ), message, timeout);
619624 }
620625 // Block message after error / success.
621626 if (blockMessage) {
622- blockNotificationFor ( 30000 ) ;
627+ silenceNotificationUntil_ = current + 30000 ;
623628 }
624629}
625630
@@ -683,12 +688,16 @@ void RimeEngine::deploy() {
683688 RIME_DEBUG () << " Rime Deploy" ;
684689 releaseAllSession (true );
685690 api_->finalize ();
691+ allowNotification ();
686692 rimeStart (true );
687693}
688694
689- void RimeEngine::sync () {
695+ void RimeEngine::sync (bool userTriggered ) {
690696 RIME_DEBUG () << " Rime Sync user data" ;
691697 releaseAllSession (true );
698+ if (userTriggered) {
699+ allowNotification ();
700+ }
692701 api_->sync_user_data ();
693702}
694703
@@ -757,7 +766,6 @@ void RimeEngine::updateSchemaMenu() {
757766 schemaAction.connect <SimpleAction::Activated>(
758767 [this , schemaId](InputContext *ic) {
759768 auto *state = this ->state (ic);
760- blockNotificationFor (30000 );
761769 state->selectSchema (schemaId);
762770 imAction_->update (ic);
763771 });
0 commit comments