Fcitx
key.h
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2015-2015 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 
8 #ifndef _FCITX_UTILS_KEY_H_
9 #define _FCITX_UTILS_KEY_H_
10 
11 /// \addtogroup FcitxUtils
12 /// \{
13 /// \file
14 /// \brief Class to represent a key.
15 
16 #include <algorithm>
17 #include <cstddef>
18 #include <cstdint>
19 #include <string>
20 #include <vector>
21 #include <fcitx-utils/fcitxutils_export.h>
22 #include <fcitx-utils/flags.h>
23 #include <fcitx-utils/keysym.h>
24 #include <fcitx-utils/macros.h>
25 #include <ranges>
26 
27 namespace fcitx {
28 class Key;
29 using KeySym = FcitxKeySym;
30 using KeyStates = Flags<KeyState>;
31 using KeyList = std::vector<Key>;
32 
33 /// Control the behavior of toString function.
34 enum class KeyStringFormat {
35  /// Can be used to parse from a string.
36  Portable,
37  /// Return the human readable string in localized format.
38  Localized,
39 };
40 
41 /// Describe a Key in fcitx.
42 class FCITXUTILS_EXPORT Key {
43 public:
44  explicit Key(KeySym sym = FcitxKey_None, KeyStates states = KeyStates(),
45  int code = 0)
46  : sym_(sym), states_(states), code_(code) {}
47 
48  /// Parse a key from string. If string is invalid, it will be set to
49  /// FcitxKey_None
50  explicit Key(const char *keyString);
51 
52  /// Parse a key from std::string.
53  /// \see fcitx::Key::Key(const char *)
54  explicit Key(const std::string &keyString) : Key(keyString.c_str()) {}
55 
56  FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE(Key)
57 
58  /// Create a key code based key with empty key symbol.
59  static Key fromKeyCode(int code = 0, KeyStates states = KeyStates()) {
60  return Key(FcitxKey_None, states, code);
61  }
62 
63  /// Check if key is exactly same.
64  bool operator==(const Key &key) const {
65  return sym_ == key.sym_ && states_ == key.states_ && code_ == key.code_;
66  }
67 
68  /// Check if key is not same;
69  bool operator!=(const Key &key) const { return !operator==(key); }
70 
71  /// Check if current key match the key.
72  bool check(const Key &key) const;
73 
74  /// Check if current key match the sym and states.
75  /// \see fcitx::Key::check(const Key &key)
76  bool check(KeySym sym = FcitxKey_None,
77  KeyStates states = KeyStates()) const {
78  return check(Key(sym, states));
79  }
80 
81  /**
82  * Check if current key is a key release of given modifier only key.
83  *
84  * This is a very specialized check for modifier release case.
85  * And it's designed to handle modifier only key.
86  *
87  * For example, if Alt+Shift_L is pressed, then the following release key of
88  * this event can be either: Alt+Shift+Shift_L, or Alt+Shift+Meta_{L,R}.
89  * This is because: Alt -> Meta_{L,R}, if alt is released first, then it
90  * will produce Alt+Shift+Meta_{L,R}. If shift is released first, then it
91  * will produce Alt+Shift+Shift_L.
92  *
93  * Return false if key is not a modifier.
94  */
95  bool isReleaseOfModifier(const Key &key) const;
96 
97  /**
98  * Check if key is digit key or keypad digit key.
99  *
100  * Since 5.0.20, it will also return true for keypad digit key.
101  * @return Whether the key is a digit key without modifier.
102  */
103  bool isDigit() const;
104 
105  /**
106  * Return the value of digit key.
107  *
108  * The key must not have modifier.
109  * For example, FcitxKey_7 will return 7.
110  *
111  * @return value of digit key. If the key is not a digit key, it returns -1.
112  * @since 5.0.20
113  */
114  int digit() const;
115 
116  /**
117  * Return index when using digit key for selection.
118  *
119  * The return value will return in the order of 1234567890.
120  *
121  * @return index of digit key. If the key is not a digit key, it returns -1.
122  * @since 5.0.20
123  * @see digit
124  */
125  int digitSelection(KeyStates states = KeyStates()) const;
126 
127  /// Check if key is upper case.
128  bool isUAZ() const;
129 
130  /// Check if key is lower case.
131  bool isLAZ() const;
132 
133  /// Check if key is in the range of ascii and has no states.
134  bool isSimple() const;
135 
136  /// Check if the key is a modifier press.
137  bool isModifier() const;
138 
139  /// Check if this key will cause cursor to move, e.g. arrow key and page up/
140  /// down.
141  bool isCursorMove() const;
142 
143  /// Check if this key is a key pad key.
144  bool isKeyPad() const;
145 
146  /// Check if states has modifier.
147  bool hasModifier() const;
148 
149  /// Check if states has virtual bit
150  bool isVirtual() const;
151 
152  /// \brief Normalize a key, usually used when key is from frontend.
153  ///
154  /// states will be filtered to have only ctrl alt shift and super.
155  /// Shift will be removed if it is key symbol is a-z/A-Z.
156  /// Shift + any other modifier and a-z will be reset to A-Z. So
157  /// key in configuration does not need to bother the case.
158  Key normalize() const;
159 
160  /// \brief Convert key to a string.
161  ///
162  /// \arg format will control the format of return value.
163  std::string
164  toString(KeyStringFormat format = KeyStringFormat::Portable) const;
165 
166  /// Check if the sym is not FcitxKey_None or FcitxKey_VoidSymbol.
167  bool isValid() const;
168 
169  inline KeySym sym() const { return sym_; }
170  inline KeyStates states() const { return states_; }
171  inline int code() const { return code_; }
172 
173  /// Convert the modifier symbol to its corresponding states.
174  static KeyStates keySymToStates(KeySym sym);
175 
176  /// Convert a key symbol string to KeySym.
177  static KeySym keySymFromString(const std::string &keyString);
178 
179  /// \brief Convert keysym to a string.
180  ///
181  /// \arg format will control the format of return value.
182  static std::string
183  keySymToString(KeySym sym,
185 
186  /// Convert unicode to key symbol. Useful when you want to create a
187  /// synthetic key event.
188  static KeySym keySymFromUnicode(uint32_t unicode);
189 
190  /// Convert keysym to a unicode. Will return a valid value UCS-4 value if
191  /// this key may produce a character.
192  static uint32_t keySymToUnicode(KeySym sym);
193 
194  /// Convert keysym to a unicode string. Will return a non empty value UTF-8
195  /// string if this key may produce a character.
196  /// \see fcitx::Key::keySymToUnicode
197  static std::string keySymToUTF8(KeySym sym);
198 
199  /// Parse a list of key string into a KeyList.
200  static KeyList keyListFromString(const std::string &str);
201 
202  /// Convert a key list to string.
203  template <typename Container>
204  static std::string
205  keyListToString(const Container &container,
207  std::string result;
208  bool first = true;
209  for (const auto &k : container) {
210  if (first) {
211  first = false;
212  } else {
213  result += " ";
214  }
215  result += k.toString(format);
216  }
217  return result;
218  }
219 
220  /// Check the current key against a key list.
221  /// \see fcitx::Key::check
222  template <typename Container>
223  bool checkKeyList(const Container &c) const {
224  return std::ranges::find_if(c, [this](const Key &toCheck) {
225  return check(toCheck);
226  }) != std::ranges::end(c);
227  }
228 
229  /// Check the current key against a key list and get the matched key index.
230  /// \return Returns the matched key index or -1 if there is no match.
231  /// \see fcitx::Key::check
232  template <typename Container>
233  int keyListIndex(const Container &c) const {
234  size_t idx = 0;
235  for (auto &toCheck : c) {
236  if (check(toCheck)) {
237  break;
238  }
239  idx++;
240  }
241  if (idx == c.size()) {
242  return -1;
243  }
244  return static_cast<int>(idx);
245  }
246 
247 private:
248  KeySym sym_;
249  KeyStates states_;
250  int code_;
251 };
252 } // namespace fcitx
253 
254 #endif // _FCITX_UTILS_KEY_H_
Describe a Key in fcitx.
Definition: key.h:42
bool operator!=(const Key &key) const
Check if key is not same;.
Definition: key.h:69
bool checkKeyList(const Container &c) const
Check the current key against a key list.
Definition: key.h:223
Definition: action.cpp:17
KeyStringFormat
Control the behavior of toString function.
Definition: key.h:34
Can be used to parse from a string.
bool operator==(const Key &key) const
Check if key is exactly same.
Definition: key.h:64
bool check(KeySym sym=FcitxKey_None, KeyStates states=KeyStates()) const
Check if current key match the sym and states.
Definition: key.h:76
int keyListIndex(const Container &c) const
Check the current key against a key list and get the matched key index.
Definition: key.h:233
Return the human readable string in localized format.
Key sym related types.
Helper template class to make easier to use type safe enum flags.
static std::string keyListToString(const Container &container, KeyStringFormat format=KeyStringFormat::Portable)
Convert a key list to string.
Definition: key.h:205
Key(const std::string &keyString)
Parse a key from std::string.
Definition: key.h:54