1 /*
2  * SPDX-FileCopyrightText: 2016-2016 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_INSTANCE_H_
8 #define _FCITX_INSTANCE_H_
9 
10 #include <memory>
11 #include <fcitx-utils/connectableobject.h>
12 #include <fcitx-utils/handlertable.h>
13 #include <fcitx-utils/macros.h>
14 #include <fcitx/event.h>
15 #include <fcitx/globalconfig.h>
16 #include <fcitx/text.h>
17 #include "fcitxcore_export.h"
18 
19 #define FCITX_INVALID_COMPOSE_RESULT 0xffffffff
20 
21 namespace fcitx {
22 
23 class InputContext;
24 class KeyEvent;
25 class InstancePrivate;
26 class EventLoop;
27 class AddonManager;
28 class InputContextManager;
29 class InputMethodManager;
30 class InputMethodEngine;
31 class InputMethodEntry;
32 class UserInterfaceManager;
33 class GlobalConfig;
34 class FocusGroup;
35 
36 typedef std::function<void(Event &event)> EventHandler;
37 
38 /**
39  * The event handling phase of event pipeline.
40  */
41 enum class EventWatcherPhase {
42     /**
43      * Handler executed before input method.
44      *
45      * Useful for addons that want to implement an independent mode.
46      *
47      * A common workflow of such addon is:
48      * 1. Check a hotkey in PostInputMethod phase to trigger the mode
49      * 2. Handle all the key event in PreInputMethod phase just like regular
50      * input method.
51      */
52     PreInputMethod,
53     /**
54      * Handlers to be executed right after input method.
55      *
56      * The input method keyEvent is registered with an internal handler. So all
57      * the new handler in this phase will still executed after input method.
58      */
59     InputMethod,
60     /**
61      * Handlers to be executed after input method.
62      *
63      * common use case is when you want to implement a key that triggers a
64      * standalone action.
65      */
66     PostInputMethod,
67     /// Internal phase to be executed first
68     ReservedFirst,
69     /// Internal phase to be executed last
70     ReservedLast,
71     Default = PostInputMethod
72 };
73 
74 struct FCITXCORE_EXPORT InstanceQuietQuit : public std::exception {};
75 
76 /**
77  * An instance represents a standalone Fcitx instance. Usually there is only one
78  * of such object.
79  *
80  * Fcitx Instance provides the access to all the addons and sub components. It
81  * also provides a event pipeline for handling input method related event.
82  */
83 class FCITXCORE_EXPORT Instance : public ConnectableObject {
84 public:
85     /**
86      * A main function like construct to be used to create Fcitx Instance.
87      *
88      * For more details, see --help of fcitx5 command.
89      *
90      * @param argc number of argument
91      * @param argv command line arguments
92      */
93     Instance(int argc, char *argv[]);
94 
95     ~Instance();
96 
initialized()97     bool initialized() const { return !!d_ptr; }
98 
99     /**
100      * Set the pipe forwarding unix signal information.
101      *
102      * Fcitx Instance is running within its own thread, usually main thread. In
103      * order to make it handle signal correctly in a thread-safe way, it is
104      * possible to set a file descriptor that write the signal number received
105      * by the signal handler. Usually this is done through a self-pipe. This is
106      * already handled by Fcitx default server implementation, normal addon user
107      * should not touch this. The common usecase is when you want to embed Fcitx
108      * into your own program.
109      *
110      * @param fd file descriptor
111      */
112     void setSignalPipe(int fd);
113 
114     /**
115      * Start the event loop of Fcitx.
116      *
117      * @return return value that can be used as main function return code.
118      */
119     int exec();
120 
121     /**
122      * Check whether command line specify if it will replace an existing fcitx
123      * server.
124      *
125      * This function is only useful if your addon provides a way to replace
126      * existing fcitx server. Basically it is checking whether -r is passed to
127      * fcitx command line.
128      *
129      * @return whether to replace existing fcitx server. Default value is false.
130      */
131     bool willTryReplace() const;
132 
133     /**
134      * Check whether command line specify whether to keep fcitx running.
135      *
136      * There could be multiple display server, such as X/Wayland/etc. Fcitx
137      * usually will exit when the connection is closed. Command line -k can
138      * override this behavior and keep Fcitx running.
139      *
140      * @return whether to exit after main display is disconnected.
141      */
142     bool exitWhenMainDisplayDisconnected() const;
143 
144     /**
145      * Check whether fcitx is in exiting process.
146      *
147      * @return
148      */
149     bool exiting() const;
150 
151     /// Get the fcitx event loop.
152     EventLoop &eventLoop();
153 
154     /// Get the addon manager.
155     AddonManager &addonManager();
156 
157     /// Get the input context manager
158     InputContextManager &inputContextManager();
159 
160     /// Get the user interface manager
161     UserInterfaceManager &userInterfaceManager();
162 
163     /// Get the input method manager
164     InputMethodManager &inputMethodManager();
165 
166     /// Get the input method manager
167     const InputMethodManager &inputMethodManager() const;
168 
169     /// Get the global config.
170     GlobalConfig &globalConfig();
171 
172     // TODO: Merge this when we can break API.
173     bool postEvent(Event &event);
postEvent(Event && event)174     bool postEvent(Event &&event) { return postEvent(event); }
175 
176     /**
177      * Put a event to the event pipe line.
178      *
179      * @param event Input method event
180      * @return return the value of event.accepted()
181      */
182     bool postEvent(Event &event) const;
postEvent(Event && event)183     bool postEvent(Event &&event) const { return postEvent(event); }
184 
185     /**
186      * Add a callback to for certain event type.
187      *
188      * @param type event type
189      * @param phase the stage that callback will be executed.
190      * @param callback callback function.
191      * @return Handle to the callback, the callback will be removed when it is
192      * deleted.
193      */
194     FCITX_NODISCARD std::unique_ptr<HandlerTableEntry<EventHandler>>
195     watchEvent(EventType type, EventWatcherPhase phase, EventHandler callback);
196 
197     /// Return the unique name of input method for given input context.
198     std::string inputMethod(InputContext *ic);
199 
200     /// Return the input method entry for given input context.
201     const InputMethodEntry *inputMethodEntry(InputContext *ic);
202 
203     /// Return the input method engine object for given input context.
204     InputMethodEngine *inputMethodEngine(InputContext *ic);
205 
206     /// Return the input method engine object for given unique input method
207     /// name.
208     InputMethodEngine *inputMethodEngine(const std::string &name);
209 
210     /**
211      * Return the input method icon for input context.
212      *
213      * It will fallback to input-keyboard by default if no input method is
214      * available.
215      *
216      * @param ic input context
217      * @return icon name.
218      *
219      * @see InputMethodEngine::subModeIcon
220      */
221     std::string inputMethodIcon(InputContext *ic);
222 
223     /**
224      * Return the input method label for input context.
225      *
226      * @param ic input context
227      * @return label.
228      *
229      * @see InputMethodEngine::subModeLabel
230      * @since 5.0.11
231      */
232     std::string inputMethodLabel(InputContext *ic);
233 
234     /**
235      * Handle current XCompose state.
236      *
237      * @param ic input context.
238      * @param keysym key symbol.
239      *
240      * @return unicode
241      *
242      * @see processComposeString
243      */
244     FCITXCORE_DEPRECATED uint32_t processCompose(InputContext *ic,
245                                                  KeySym keysym);
246 
247     /**
248      * Handle current XCompose state.
249      *
250      * @param ic input context.
251      * @param keysym key symbol.
252      *
253      * @return the composed string, if it returns nullopt, it means compose is
254      * invalid.
255      *
256      * @see processComposeString
257      * @since 5.0.4
258      */
259     std::optional<std::string> processComposeString(InputContext *ic,
260                                                     KeySym keysym);
261 
262     /// Reset the compose state.
263     void resetCompose(InputContext *inputContext);
264 
265     /**
266      * Update the commit string to frontend
267      *
268      * This function should be not be used directly since it is already used
269      * internally by InputContext::commitString.
270      *
271      * @param inputContext input context
272      * @param orig original string
273      * @return the updated string.
274      * @see InputContext::commitString
275      */
276     std::string commitFilter(InputContext *inputContext,
277                              const std::string &orig);
278     /**
279      * Update the string that will be displayed in user interface.
280      *
281      * This function should only be used by frontend for client preedit, or user
282      * interface, for the other field in input panel.
283      *
284      * @see InputPanel
285      *
286      * @param inputContext input context
287      * @param orig orig text
288      * @return fcitx::Text
289      */
290     Text outputFilter(InputContext *inputContext, const Text &orig);
291 
292     FCITX_DECLARE_SIGNAL(Instance, CommitFilter,
293                          void(InputContext *inputContext, std::string &orig));
294     FCITX_DECLARE_SIGNAL(Instance, OutputFilter,
295                          void(InputContext *inputContext, Text &orig));
296     FCITX_DECLARE_SIGNAL(Instance, KeyEventResult,
297                          void(const KeyEvent &keyEvent));
298     /**
299      * \deprecated
300      */
301     FCITX_DECLARE_SIGNAL(Instance, CheckUpdate, bool());
302 
303     /// Return a focused input context.
304     InputContext *lastFocusedInputContext();
305     /// Return the most recent focused input context. If there isn't such ic,
306     /// return the last unfocused input context.
307     InputContext *mostRecentInputContext();
308 
309     /// All user interface update is batched internally. This function will
310     /// flush all the batched UI update immediately.
311     void flushUI();
312 
313     // controller functions.
314 
315     /// Exit the fcitx event loop
316     void exit();
317 
318     /// Restart fcitx instance, this should only be used within a regular Fcitx
319     /// server, not within embedded mode.
320     void restart();
321 
322     /// Launch configtool
323     void configure();
324 
325     FCITXCORE_DEPRECATED void configureAddon(const std::string &addon);
326     FCITXCORE_DEPRECATED void configureInputMethod(const std::string &imName);
327 
328     /// Return the name of current user interface addon.
329     std::string currentUI();
330 
331     /// Return the addon name of given input method.
332     std::string addonForInputMethod(const std::string &imName);
333 
334     // Following functions are operations against lastFocusedInputContext
335 
336     /// Activate last focused input context. (Switch to the active input method)
337     void activate();
338 
339     /// Deactivate last focused input context. (Switch to the first input
340     /// method)
341     void deactivate();
342 
343     /// Toggle between the first input method and active input method.
344     void toggle();
345 
346     /// Reset the input method configuration and recreate based on system
347     /// language.
348     void resetInputMethodList();
349 
350     /// Return a fcitx5-remote compatible value for the state.
351     int state();
352 
353     /// Reload global config.
354     void reloadConfig();
355     /// Reload certain addon config.
356     void reloadAddonConfig(const std::string &addonName);
357     /// Load newly installed input methods and addons.
358     void refresh();
359 
360     /// Return the current input method of last focused input context.
361     std::string currentInputMethod();
362 
363     /// Set the input method of last focused input context.
364     void setCurrentInputMethod(const std::string &imName);
365 
366     /**
367      * Set the input method of given input context.
368      *
369      * The input method need to be within the current group. Local parameter can
370      * be used to set the input method only for this input context.
371      *
372      * @param ic input context
373      * @param imName unique name of a input method
374      * @param local
375      */
376     void setCurrentInputMethod(InputContext *ic, const std::string &imName,
377                                bool local);
378 
379     /// Enumerate input method group
380     bool enumerateGroup(bool forward);
381 
382     /// Enumerate input method with in current group
383     void enumerate(bool forward);
384 
385     /**
386      * Get the default focus group with given display hint.
387      *
388      * This function is used by frontend to assign a focus group from an unknown
389      * display server.
390      *
391      * @param displayHint Display server hint, it can something like be x11: /
392      * wayland:
393      * @return focus group
394      */
395     FocusGroup *defaultFocusGroup(const std::string &displayHint = {});
396 
397     /**
398      * Set xkb RLVMO tuple for given display
399      *
400      * @param display display name
401      * @param rule xkb rule name
402      * @param model xkb model name
403      * @param options xkb option
404      */
405     void setXkbParameters(const std::string &display, const std::string &rule,
406                           const std::string &model, const std::string &options);
407 
408     /// Update xkb state mask for given display
409     void updateXkbStateMask(const std::string &display, uint32_t depressed_mods,
410                             uint32_t latched_mods, uint32_t locked_mods);
411 
412     /**
413      * Show a small popup with input popup window with current input method
414      * information.
415      *
416      * This is useful for input method that has multiple sub modes. It can be
417      * called with switching sub modes within the input method.
418      *
419      * @param ic input context.
420      */
421     void showInputMethodInformation(InputContext *ic);
422 
423     /**
424      * Check if need to invoke Instance::refresh.
425      *
426      * @return need update
427      * @see Instance::refresh
428      */
429     bool checkUpdate() const;
430 
431     /// Return the version string of Fcitx.
432     static const char *version();
433 
434 private:
435     void initialize();
436     void handleSignal();
437     void save();
438 
439     bool canTrigger() const;
440     bool canAltTrigger(InputContext *ic) const;
441     bool canEnumerate(InputContext *ic) const;
442     bool canChangeGroup() const;
443     bool trigger(InputContext *ic, bool totallyReleased);
444     bool altTrigger(InputContext *ic);
445     bool activate(InputContext *ic);
446     bool deactivate(InputContext *ic);
447     bool enumerate(InputContext *ic, bool forward);
448     bool toggle(InputContext *ic, InputMethodSwitchedReason reason =
449                                       InputMethodSwitchedReason::Trigger);
450 
451     void activateInputMethod(InputContextEvent &event);
452     void deactivateInputMethod(InputContextEvent &event);
453 
454     std::unique_ptr<InstancePrivate> d_ptr;
455     FCITX_DECLARE_PRIVATE(Instance);
456 };
457 }; // namespace fcitx
458 
459 #endif // _FCITX_INSTANCE_H_
460