Fcitx
addoninstance.h
Go to the documentation of this file.
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_ADDONINSTANCE_H_
8 #define _FCITX_ADDONINSTANCE_H_
9 
10 #include <functional>
11 #include <memory>
12 #include <type_traits>
13 #include <unordered_map>
14 #include <fcitx-config/configuration.h>
15 #include <fcitx-utils/library.h>
16 #include <fcitx-utils/metastring.h>
17 #include <fcitx/addoninstance_details.h>
18 #include "fcitxcore_export.h"
19 
20 /// \addtogroup FcitxCore
21 /// \{
22 /// \file
23 /// \brief Addon For fcitx.
24 
25 namespace fcitx {
26 
27 /// \brief Base class for any addon in fcitx.
28 /// To implement addon in fcitx, you will need to create a sub class for this
29 /// class.
30 ///
31 /// To make an SharedLibrary Addon, you will also need to use
32 /// FCITX_ADDON_FACTORY to export the factory for addon.
33 ///
34 /// An addon can export several function to be invoked by other addons.
35 /// When you need to do so, you will need some extra command in your
36 /// CMakeLists.txt, and using FCITX_ADDON_DECLARE_FUNCTION and
37 /// FCITX_ADDON_EXPORT_FUNCTION.
38 /// \code{.unparsed}
39 /// fcitx5_export_module(XCB
40 /// TARGET xcb
41 /// BUILD_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}"
42 /// HEADERS xcb_public.h INSTALL)
43 /// \endcode
44 ///
45 /// First you will need to create a header file with exported addon function.
46 /// E.g. dummyaddon_public.h
47 /// \code{.cpp}
48 /// FCITX_ADDON_DECLARE_FUNCTION(DummyAddon, addOne, int(int));
49 /// \endcode
50 /// This file declares a function addOne for DummyAddon, with function signature
51 /// int(int).
52 ///
53 /// Then, when you implement the class, add using the macro
54 /// FCITX_ADDON_EXPORT_FUNCTION to the addon class.
55 /// \code{.cpp}
56 /// class DummyAddon : public fcitx::AddonInstance {
57 /// public:
58 /// int addOne(int a) { return a + 1; }
59 ///
60 /// FCITX_ADDON_EXPORT_FUNCTION(DummyAddon, addOne);
61 /// };
62 /// \endcode
63 /// This macro will register the function and check the signature against the
64 /// actual function to make sure they have the same signature.
65 ///
66 /// In order to invoke the function in other code, you will need to first obtain
67 /// the pointer to the addon via AddonManager. Then invoke it by
68 /// \code{.cpp}
69 /// addon->call<fcitx::IDummyAddon::addOne>(7);
70 /// \endcode
71 class FCITXCORE_EXPORT AddonInstance {
72 public:
73  AddonInstance();
74  virtual ~AddonInstance();
75 
76  /// Reload configuration from disk.
77  virtual void reloadConfig() {}
78 
79  /// Save any relevant data. Usually, it will be invoked when fcitx exits.
80  virtual void save() {}
81 
82  /// Get the configuration.
83  virtual const Configuration *getConfig() const { return nullptr; }
84 
85  /// Set configuration from Raw Config.
86  virtual void setConfig(const RawConfig &) {}
87  virtual const Configuration *getSubConfig(const std::string &) const {
88  return nullptr;
89  }
90  virtual void setSubConfig(const std::string &, const RawConfig &) {}
91 
92  template <typename Signature, typename... Args>
93  typename std::function<Signature>::result_type
94  callWithSignature(const std::string &name, Args &&...args) {
95  auto *adaptor = findCall(name);
96  auto erasureAdaptor =
97  static_cast<AddonFunctionAdaptorErasure<Signature> *>(adaptor);
98  return erasureAdaptor->callback(std::forward<Args>(args)...);
99  }
100  template <typename MetaSignatureString, typename... Args>
101  auto callWithMetaString(Args &&...args) {
102  return callWithSignature<
103  AddonFunctionSignatureType<MetaSignatureString>>(
104  MetaSignatureString::data(), std::forward<Args>(args)...);
105  }
106 
107  /// Call an exported function for this addon.
108  template <typename MetaType, typename... Args>
109  auto call(Args &&...args) {
110  return callWithSignature<typename MetaType::Signature>(
111  MetaType::Name::data(), std::forward<Args>(args)...);
112  }
113 
114  void registerCallback(const std::string &name,
115  AddonFunctionAdaptorBase *adaptor);
116 
117 private:
118  AddonFunctionAdaptorBase *findCall(const std::string &name);
119  std::unique_ptr<AddonInstancePrivate> d_ptr;
120  FCITX_DECLARE_PRIVATE(AddonInstance);
121 };
122 } // namespace fcitx
123 
124 #define FCITX_ADDON_DECLARE_FUNCTION(NAME, FUNCTION, SIGNATURE...) \
125  namespace fcitx { \
126  template <> \
127  struct AddonFunctionSignature<fcitxMakeMetaString(#NAME "::" #FUNCTION)> { \
128  typedef std::remove_reference_t<decltype(std::declval<SIGNATURE>())> \
129  type; \
130  }; \
131  namespace I##NAME { \
132  struct FUNCTION { \
133  typedef fcitxMakeMetaString(#NAME "::" #FUNCTION) Name; \
134  using Signature = AddonFunctionSignatureType<Name>; \
135  }; \
136  } \
137  }
138 
139 #define FCITX_ADDON_EXPORT_FUNCTION(CLASS, FUNCTION) \
140  decltype(::fcitx::MakeAddonFunctionAdaptor( \
141  &CLASS::FUNCTION)) FUNCTION##Adaptor{#CLASS "::" #FUNCTION, this, \
142  &CLASS::FUNCTION}; \
143  static_assert( \
144  std::is_same<decltype(::fcitx::MakeAddonFunctionAdaptor( \
145  &CLASS::FUNCTION))::Signature, \
146  ::fcitx::AddonFunctionSignatureType<fcitxMakeMetaString( \
147  #CLASS "::" #FUNCTION)>>::value, \
148  "Signature doesn't match");
149 
150 #define FCITX_ADDON_FACTORY(ClassName) \
151  extern "C" { \
152  FCITXCORE_EXPORT \
153  ::fcitx::AddonFactory *fcitx_addon_factory_instance() { \
154  static ClassName factory; \
155  return &factory; \
156  } \
157  }
158 
159 /// A convenient macro to obtain the addon pointer of another addon.
160 #define FCITX_ADDON_DEPENDENCY_LOADER(NAME, ADDONMANAGER) \
161  auto NAME() { \
162  if (_##NAME##FirstCall_) { \
163  _##NAME##_ = (ADDONMANAGER).addon(#NAME, true); \
164  _##NAME##FirstCall_ = false; \
165  } \
166  return _##NAME##_; \
167  } \
168  bool _##NAME##FirstCall_ = true; \
169  ::fcitx::AddonInstance *_##NAME##_ = nullptr;
170 
171 #endif // _FCITX_ADDONINSTANCE_H_
virtual void reloadConfig()
Reload configuration from disk.
Definition: addoninstance.h:77
virtual const Configuration * getConfig() const
Get the configuration.
Definition: addoninstance.h:83
virtual void setConfig(const RawConfig &)
Set configuration from Raw Config.
Definition: addoninstance.h:86
Definition: action.cpp:12
virtual void save()
Save any relevant data. Usually, it will be invoked when fcitx exits.
Definition: addoninstance.h:80
Class to handler dynamic library.
Base class for any addon in fcitx.
Definition: addoninstance.h:71
auto call(Args &&...args)
Call an exported function for this addon.
Static string based on template argument.