1 /*
2  * SPDX-FileCopyrightText: 2017~2017 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  */
6 #ifndef _FCITX_RIMEENGINE_H_
7 #define _FCITX_RIMEENGINE_H_
8 
9 #include "rimeservice.h"
10 #include <fcitx-config/configuration.h>
11 #include <fcitx-config/iniparser.h>
12 #include <fcitx-utils/event.h>
13 #include <fcitx-utils/eventdispatcher.h>
14 #include <fcitx-utils/i18n.h>
15 #include <fcitx-utils/library.h>
16 #include <fcitx-utils/log.h>
17 #include <fcitx/action.h>
18 #include <fcitx/addonfactory.h>
19 #include <fcitx/addonmanager.h>
20 #include <fcitx/icontheme.h>
21 #include <fcitx/inputcontextproperty.h>
22 #include <fcitx/inputmethodengine.h>
23 #include <fcitx/instance.h>
24 #include <fcitx/menu.h>
25 #include <memory>
26 #include <rime_api.h>
27 
28 namespace fcitx {
29 
30 class RimeState;
31 
32 FCITX_CONFIGURATION(
33     RimeEngineConfig,
34     Option<bool> showPreeditInApplication{this, "PreeditInApplication",
35                                           _("Show preedit within application"),
36                                           false};
37     Option<bool> commitWhenDeactivate{
38         this, "Commit when deactivate",
39         _("Commit current text when deactivating"), true};
40 #ifdef FCITX_RIME_LOAD_PLUGIN
41     Option<bool> autoloadPlugins{this, "AutoloadPlugins",
42                                  _("Load available plugins automatically"),
43                                  false};
44     Option<std::vector<std::string>> plugins{this, "Plugins", _("Plugins"),
45                                              std::vector<std::string>()};
46     Option<std::vector<std::string>> modules{this, "Modules", _("Modules"),
47                                              std::vector<std::string>()};
48 #endif
49 );
50 
51 class RimeEngine final : public InputMethodEngineV2 {
52 public:
53     RimeEngine(Instance *instance);
54     ~RimeEngine();
instance()55     Instance *instance() { return instance_; }
56     void activate(const InputMethodEntry &entry,
57                   InputContextEvent &event) override;
58     void deactivate(const InputMethodEntry &entry,
59                     InputContextEvent &event) override;
60     void keyEvent(const InputMethodEntry &entry, KeyEvent &keyEvent) override;
61     void reloadConfig() override;
62     void reset(const InputMethodEntry &entry,
63                InputContextEvent &event) override;
64     void save() override;
factory()65     auto &factory() { return factory_; }
66 
updateAction(InputContext * inputContext)67     void updateAction(InputContext *inputContext) {
68         imAction_->update(inputContext);
69     }
70 
getConfig()71     const Configuration *getConfig() const override { return &config_; }
setConfig(const RawConfig & config)72     void setConfig(const RawConfig &config) override {
73         config_.load(config, true);
74         safeSaveAsIni(config_, "conf/rime.conf");
75         updateConfig();
76     }
77     void setSubConfig(const std::string &path, const RawConfig &) override;
78     void updateConfig();
79 
80     std::string subMode(const InputMethodEntry &, InputContext &) override;
81     std::string subModeIconImpl(const InputMethodEntry &,
82                                 InputContext &) override;
83     std::string subModeLabelImpl(const InputMethodEntry &,
84                                  InputContext &) override;
config()85     const RimeEngineConfig &config() const { return config_; }
86 
api()87     rime_api_t *api() { return api_; }
88 
89     void rimeStart(bool fullcheck);
90 
91     RimeState *state(InputContext *ic);
92 
93     FCITX_ADDON_DEPENDENCY_LOADER(dbus, instance_->addonManager());
94 
95 private:
96     static void rimeNotificationHandler(void *context_object,
97                                         RimeSessionId session_id,
98                                         const char *message_type,
99                                         const char *message_value);
100 
101     void deploy();
102     void sync();
103     void updateSchemaMenu();
104     void notify(const std::string &type, const std::string &value);
105 
106     IconTheme theme_;
107     Instance *instance_;
108     EventDispatcher eventDispatcher_;
109     rime_api_t *api_;
110     bool firstRun_ = true;
111     FactoryFor<RimeState> factory_;
112 
113     std::unique_ptr<Action> imAction_;
114     SimpleAction deployAction_;
115     SimpleAction syncAction_;
116 
117     RimeEngineConfig config_;
118 
119     FCITX_ADDON_DEPENDENCY_LOADER(notifications, instance_->addonManager());
120 
121     std::list<SimpleAction> schemActions_;
122     Menu schemaMenu_;
123 #ifdef FCITX_RIME_LOAD_PLUGIN
124     std::unordered_map<std::string, Library> pluginPool_;
125 #endif
126     std::unique_ptr<EventSourceTime> timeEvent_;
127 
128     RimeService service_{this};
129 };
130 
131 class RimeEngineFactory : public AddonFactory {
132 public:
create(AddonManager * manager)133     AddonInstance *create(AddonManager *manager) override {
134         registerDomain("fcitx5-rime", FCITX_INSTALL_LOCALEDIR);
135         return new RimeEngine(manager->instance());
136     }
137 };
138 } // namespace fcitx
139 
140 FCITX_DECLARE_LOG_CATEGORY(rime);
141 
142 #define RIME_DEBUG() FCITX_LOGC(rime, Debug)
143 #define RIME_ERROR() FCITX_LOGC(rime, Error)
144 
145 #endif // _FCITX_RIMEENGINE_H_
146