Fcitx
event.h
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_EVENT_H_
8 #define _FCITX_EVENT_H_
9 
10 #include <stdint.h>
12 #include <fcitx-utils/key.h>
13 #include <fcitx/userinterface.h>
14 #include "fcitxcore_export.h"
15 
16 namespace fcitx {
17 
18 class InputContext;
19 class FocusGroup;
20 
21 enum class ResetReason {
22  ChangeByInactivate FCITXCORE_DEPRECATED,
23  LostFocus FCITXCORE_DEPRECATED,
24  SwitchIM FCITXCORE_DEPRECATED,
25  Client
26 };
27 
28 /**
29  * The reason why input method is switched to another.
30  */
31 enum class InputMethodSwitchedReason {
32  /// Switched by trigger key
33  Trigger,
34  /// Switched by deactivate key
35  Deactivate,
36  /// Switched by alternative trigger key
37  AltTrigger,
38  /// Switched by activate key
39  Activate,
40  /// Switched by enumerate key
41  Enumerate,
42  /// Switched by group change
43  GroupChange,
44  /// Switched by capability change (e.g. password field)
45  CapabilityChanged,
46  /// miscellaneous reason
47  Other,
48 };
49 
50 /**
51  * Type of input method events.
52  */
53 enum class EventType : uint32_t {
54  EventTypeFlag = 0xffff0000,
55  UserTypeFlag = 0xffff0000,
56  // send by frontend, captured by core, input method, or module
57  InputContextEventFlag = 0x0001000,
58  // send by im, captured by frontend, or module
59  InputMethodEventFlag = 0x0002000,
60 
61  /**
62  * captured by everything
63  */
64  InstanceEventFlag = 0x0003000,
65  InputContextCreated = InputContextEventFlag | 0x1,
66  InputContextDestroyed = InputContextEventFlag | 0x2,
67  /**
68  * FocusInEvent is generated when client gets focused.
69  *
70  * @see FocusInEvent
71  */
72  InputContextFocusIn = InputContextEventFlag | 0x3,
73  /**
74  * when using lost focus
75  * this might be variance case to case. the default behavior is to commit
76  * the preedit, and resetIM.
77  *
78  * Controlled by [Output/DontCommitPreeditWhenUnfocus], this option will not
79  * work for application switch doesn't support async commit.
80  *
81  * So OnClose is called when preedit IS committed (not like
82  * CChangeByInactivate,
83  * this behavior cannot be overrided), it give im a chance to choose
84  * remember this
85  * word or not.
86  *
87  * Input method need to notice, that the commit is already DONE, do not do
88  * extra commit.
89  *
90  * @see FocusOutEvent
91  */
92  InputContextFocusOut = InputContextEventFlag | 0x4,
93  /**
94  * Key event is generated when client press or release a key.
95  * @see KeyEvent
96  */
97  InputContextKeyEvent = InputContextEventFlag | 0x5,
98  /**
99  * ResetEvent is generated
100  *
101  */
102  InputContextReset = InputContextEventFlag | 0x6,
103  InputContextSurroundingTextUpdated = InputContextEventFlag | 0x7,
104  InputContextCapabilityChanged = InputContextEventFlag | 0x8,
105  InputContextCursorRectChanged = InputContextEventFlag | 0x9,
106  InputContextCapabilityAboutToChange = InputContextEventFlag | 0xD,
107  /**
108  * when user switch to a different input method by hand
109  * such as ctrl+shift by default, or by ui,
110  * default behavior is reset IM.
111  */
112  InputContextSwitchInputMethod = InputContextEventFlag | 0xA,
113 
114  // Two convenient event after input method is actually activate and
115  // deactivated. Useful for UI to update after specific input method get
116  // activated and deactivated. Will not be emitted if the input method is not
117  // a valid one.
118  InputContextInputMethodActivated = InputContextEventFlag | 0xB,
119  InputContextInputMethodDeactivated = InputContextEventFlag | 0xC,
120  /**
121  * InvokeAction event is generated when client click on the preedit.
122  *
123  * Not all client support this feature.
124  *
125  * @since 5.0.11
126  */
127  InputContextInvokeAction = InputContextEventFlag | 0xE,
128 
129  InputContextForwardKey = InputMethodEventFlag | 0x1,
130  InputContextCommitString = InputMethodEventFlag | 0x2,
131  InputContextDeleteSurroundingText = InputMethodEventFlag | 0x3,
132  InputContextUpdatePreedit = InputMethodEventFlag | 0x4,
133  InputContextUpdateUI = InputMethodEventFlag | 0x5,
134 
135  /**
136  * This is generated when input method group changed.
137  * This would also trigger InputContextSwitchInputMethod afterwards.
138  */
139  InputMethodGroupChanged = InstanceEventFlag | 0x1,
140  /**
141  * InputMethodGroupAboutToChangeEvent is generated when input method group
142  * is about to be changed.
143  *
144  * @see InputMethodGroupAboutToChange
145  */
146  InputMethodGroupAboutToChange = InstanceEventFlag | 0x2,
147  /**
148  * UIChangedEvent is posted when the UI implementation is changed.
149  */
150  UIChanged = InstanceEventFlag | 0x3,
151  /**
152  * CheckUpdateEvent is posted when the Instance is requested to check for
153  * newly installed addons and input methods.
154  *
155  * This can be used for addons to pick up new input methods if it provides
156  * input method at runtime.
157  */
158  CheckUpdate = InstanceEventFlag | 0x4,
159  /**
160  * FocusGroupFocusChanged is posted when a focus group changed its focused
161  * input context.
162  *
163  * This is a more fine grained control over focus in and focus out event.
164  * This is more useful for UI to keep track of what input context is being
165  * focused.
166  *
167  * @see FocusInEvent
168  * @see FocusOutEvent
169  */
170  FocusGroupFocusChanged = InstanceEventFlag | 0x5,
171 };
172 
173 /**
174  * Base class for fcitx event.
175  */
176 class FCITXCORE_EXPORT Event {
177 public:
178  Event(EventType type) : type_(type) {}
179  virtual ~Event();
180 
181  /**
182  * Type of event, can be used to decide event class.
183  *
184  * @return fcitx::EventType
185  */
186  EventType type() const { return type_; }
187 
188  void accept() { accepted_ = true; }
189  /**
190  * Return value used by Instance::postEvent.
191  *
192  * @see Instance::postEvent
193  * @return bool
194  */
195  bool accepted() const { return accepted_; }
196 
197  /**
198  * Whether a event is filtered by handler.
199  *
200  * If event is filtered, it will not send to another handler.
201  * For now only keyevent from input context can be filtered.
202  *
203  * @return bool
204  */
205  virtual bool filtered() const { return false; }
206 
207  /**
208  * A helper function to check if a event is input context event.
209  *
210  * @return bool
211  */
212  bool isInputContextEvent() const {
213  auto flag = static_cast<uint32_t>(EventType::InputContextEventFlag);
214  return (static_cast<uint32_t>(type_) & flag) == flag;
215  }
216 
217 protected:
218  EventType type_;
219  bool accepted_ = false;
220 };
221 
222 class FCITXCORE_EXPORT InputContextEvent : public Event {
223 public:
224  InputContextEvent(InputContext *context, EventType type)
225  : Event(type), ic_(context) {}
226 
227  InputContext *inputContext() const { return ic_; }
228 
229 protected:
230  InputContext *ic_;
231 };
232 
233 class FCITXCORE_EXPORT KeyEventBase : public InputContextEvent {
234 public:
235  KeyEventBase(EventType type, InputContext *context, Key rawKey,
236  bool isRelease = false, int time = 0);
237  KeyEventBase(const KeyEventBase &) = default;
238 
239  /**
240  * Normalized key event.
241  *
242  * @return fcitx::Key
243  */
244  Key key() const { return key_; }
245 
246  /**
247  * It will automatically be called if input method layout does not match the
248  * system keyboard layout.
249  *
250  * @param key p_key:...
251  */
252  void setKey(const Key &key) {
253  key_ = key;
254  forward_ = true;
255  }
256 
257  /**
258  * It is designed for faking the key event. Normally should not be used.
259  *
260  * @param key key event to override.
261  * @since 5.0.4
262  */
263  void setRawKey(const Key &key) {
264  rawKey_ = key;
265  key_ = key.normalize();
266  forward_ = true;
267  }
268 
269  /**
270  * It is designed for overriding the key forward option. Normally should not
271  * be used.
272  *
273  * @param forward
274  * @since 5.0.4
275  */
276  void setForward(bool forward) { forward_ = forward; }
277 
278  /**
279  * Key event regardless of keyboard layout conversion.
280  *
281  * @return fcitx::Key
282  */
283  Key origKey() const { return origKey_; }
284 
285  /**
286  * Key event after layout conversion.
287  *
288  * Basically it is the "unnormalized" key event.
289  *
290  * @return fcitx::Key
291  */
292  Key rawKey() const { return rawKey_; }
293  bool isRelease() const { return isRelease_; }
294  int time() const { return time_; }
295 
296  /**
297  * If true, the key that produce character will commit a string.
298  *
299  * This is currently used by internal keyboard layout translation.
300  *
301  * @return bool
302  */
303  bool forward() const { return forward_; }
304 
305 protected:
306  Key key_, origKey_, rawKey_;
307  bool isRelease_;
308  int time_;
309  bool forward_ = false;
310 };
311 
312 class FCITXCORE_EXPORT KeyEvent : public KeyEventBase {
313 public:
314  KeyEvent(InputContext *context, Key rawKey, bool isRelease = false,
315  int time = 0)
316  : KeyEventBase(EventType::InputContextKeyEvent, context, rawKey,
317  isRelease, time) {}
318 
319  void filter() { filtered_ = true; }
320  bool filtered() const override { return filtered_; }
321  void filterAndAccept() {
322  filter();
323  accept();
324  }
325 
326 private:
327  bool filtered_ = false;
328 };
329 
330 class FCITXCORE_EXPORT ForwardKeyEvent : public KeyEventBase {
331 public:
332  ForwardKeyEvent(InputContext *context, Key rawKey, bool isRelease = false,
333  int time = 0)
334  : KeyEventBase(EventType::InputContextForwardKey, context, rawKey,
335  isRelease, time) {}
336 };
337 
338 class FCITXCORE_EXPORT CommitStringEvent : public InputContextEvent {
339 public:
340  CommitStringEvent(const std::string &text, InputContext *context)
341  : InputContextEvent(context, EventType::InputContextCommitString),
342  text_(text) {}
343 
344  const std::string &text() const { return text_; }
345 
346 protected:
347  std::string text_;
348 };
349 
350 class FCITXCORE_EXPORT InvokeActionEvent : public InputContextEvent {
351 public:
352  enum class Action { LeftClick, RightClick };
353  InvokeActionEvent(Action action, int cursor, InputContext *context)
354  : InputContextEvent(context, EventType::InputContextInvokeAction),
355  action_(action), cursor_(cursor) {}
356 
357  Action action() const { return action_; }
358  int cursor() const { return cursor_; }
359 
360  void filter() {
361  filtered_ = true;
362  accept();
363  }
364  bool filtered() const override { return filtered_; }
365 
366 protected:
367  Action action_;
368  int cursor_;
369  bool filtered_ = false;
370 };
371 
373  : public InputContextEvent {
374 public:
375  InputContextSwitchInputMethodEvent(InputMethodSwitchedReason reason,
376  const std::string &oldIM,
377  InputContext *context)
378  : InputContextEvent(context, EventType::InputContextSwitchInputMethod),
379  reason_(reason), oldInputMethod_(oldIM) {}
380 
381  InputMethodSwitchedReason reason() const { return reason_; }
382  const std::string &oldInputMethod() const { return oldInputMethod_; }
383 
384 protected:
385  InputMethodSwitchedReason reason_;
386  std::string oldInputMethod_;
387 };
388 
389 class FCITXCORE_EXPORT ResetEvent : public InputContextEvent {
390 public:
391  FCITXCORE_DEPRECATED ResetEvent(ResetReason reason, InputContext *context)
392  : InputContextEvent(context, EventType::InputContextReset),
393  reason_(reason) {}
394  ResetEvent(InputContext *context)
395  : InputContextEvent(context, EventType::InputContextReset),
396  reason_(ResetReason::Client) {}
397 
398  FCITXCORE_DEPRECATED ResetReason reason() const { return reason_; }
399 
400 protected:
401  ResetReason reason_;
402 };
403 
404 class FCITXCORE_EXPORT InputContextUpdateUIEvent : public InputContextEvent {
405 public:
407  InputContext *context, bool immediate = false)
408  : InputContextEvent(context, EventType::InputContextUpdateUI),
409  component_(component), immediate_(immediate) {}
410 
411  UserInterfaceComponent component() const { return component_; }
412  bool immediate() const { return immediate_; }
413 
414 protected:
415  UserInterfaceComponent component_;
416  bool immediate_;
417 };
418 
419 class FCITXCORE_EXPORT InputMethodNotificationEvent : public InputContextEvent {
420 public:
421  InputMethodNotificationEvent(EventType type, const std::string &name,
422  InputContext *context)
423  : InputContextEvent(context, type), name_(name) {}
424 
425  const std::string &name() const { return name_; }
426 
427 protected:
428  std::string name_;
429 };
430 
431 class FCITXCORE_EXPORT InputMethodActivatedEvent
433 public:
434  InputMethodActivatedEvent(const std::string &name, InputContext *context)
436  EventType::InputContextInputMethodActivated, name, context) {}
437 };
438 
439 class FCITXCORE_EXPORT InputMethodDeactivatedEvent
441 public:
442  InputMethodDeactivatedEvent(const std::string &name, InputContext *context)
444  EventType::InputContextInputMethodDeactivated, name, context) {}
445 };
446 
447 #define FCITX_DEFINE_SIMPLE_EVENT(NAME, TYPE, ARGS...) \
448  struct FCITXCORE_EXPORT NAME##Event : public InputContextEvent { \
449  NAME##Event(InputContext *ic) \
450  : InputContextEvent(ic, EventType::TYPE) {} \
451  }
452 
453 FCITX_DEFINE_SIMPLE_EVENT(InputContextCreated, InputContextCreated);
454 FCITX_DEFINE_SIMPLE_EVENT(InputContextDestroyed, InputContextDestroyed);
455 FCITX_DEFINE_SIMPLE_EVENT(FocusIn, InputContextFocusIn);
456 FCITX_DEFINE_SIMPLE_EVENT(FocusOut, InputContextFocusOut);
457 FCITX_DEFINE_SIMPLE_EVENT(SurroundingTextUpdated,
458  InputContextSurroundingTextUpdated);
459 FCITX_DEFINE_SIMPLE_EVENT(CursorRectChanged, InputContextCursorRectChanged);
460 FCITX_DEFINE_SIMPLE_EVENT(UpdatePreedit, InputContextUpdatePreedit);
461 
462 class FCITXCORE_EXPORT InputMethodGroupChangedEvent : public Event {
463 public:
465  : Event(EventType::InputMethodGroupChanged) {}
466 };
467 
468 class FCITXCORE_EXPORT InputMethodGroupAboutToChangeEvent : public Event {
469 public:
471  : Event(EventType::InputMethodGroupAboutToChange) {}
472 };
473 
474 class FCITXCORE_EXPORT UIChangedEvent : public Event {
475 public:
476  UIChangedEvent() : Event(EventType::UIChanged) {}
477 };
478 
479 class FCITXCORE_EXPORT CheckUpdateEvent : public Event {
480 public:
481  CheckUpdateEvent() : Event(EventType::CheckUpdate) {}
482 
483  /// Make checking update short circuit. If anything need a refresh, just
484  /// simply break.
485  void setHasUpdate() {
486  filtered_ = true;
487  accept();
488  }
489  bool filtered() const override { return filtered_; }
490 
491 private:
492  bool filtered_ = false;
493 };
494 
495 /**
496  * Notify a focus change for focus group.
497  *
498  * @since 5.0.11
499  */
500 class FCITXCORE_EXPORT FocusGroupFocusChangedEvent : public Event {
501 public:
503  InputContext *newFocus)
504  : Event(EventType::FocusGroupFocusChanged), group_(group),
505  oldFocus_(oldFocus), newFocus_(newFocus) {}
506 
507  FocusGroup *group() const { return group_; }
508  InputContext *oldFocus() const { return oldFocus_; };
509  InputContext *newFocus() const { return newFocus_; };
510 
511 private:
512  FocusGroup *group_;
513  InputContext *oldFocus_;
514  InputContext *newFocus_;
515 };
516 
517 class FCITXCORE_EXPORT CapabilityEvent : public InputContextEvent {
518 public:
519  CapabilityEvent(InputContext *ic, EventType type, CapabilityFlags oldFlags,
520  CapabilityFlags newFlags)
521  : InputContextEvent(ic, type), oldFlags_(oldFlags),
522  newFlags_(newFlags) {}
523 
524  auto oldFlags() const { return oldFlags_; }
525  auto newFlags() const { return newFlags_; }
526 
527 protected:
528  const CapabilityFlags oldFlags_;
529  const CapabilityFlags newFlags_;
530 };
531 
532 class FCITXCORE_EXPORT CapabilityChangedEvent : public CapabilityEvent {
533 public:
535  CapabilityFlags newFlags)
536  : CapabilityEvent(ic, EventType::InputContextCapabilityChanged,
537  oldFlags, newFlags) {}
538 };
539 
540 class FCITXCORE_EXPORT CapabilityAboutToChangeEvent : public CapabilityEvent {
541 public:
543  CapabilityFlags newFlags)
544  : CapabilityEvent(ic, EventType::InputContextCapabilityAboutToChange,
545  oldFlags, newFlags) {}
546 };
547 } // namespace fcitx
548 
549 #endif // _FCITX_EVENT_H_
Describe a Key in fcitx.
Definition: key.h:40
EventType type() const
Type of event, can be used to decide event class.
Definition: event.h:186
void setHasUpdate()
Make checking update short circuit.
Definition: event.h:485
bool filtered() const override
Whether a event is filtered by handler.
Definition: event.h:320
Key origKey() const
Key event regardless of keyboard layout conversion.
Definition: event.h:283
Notify a focus change for focus group.
Definition: event.h:500
bool isInputContextEvent() const
A helper function to check if a event is input context event.
Definition: event.h:212
void setRawKey(const Key &key)
It is designed for faking the key event.
Definition: event.h:263
bool filtered() const override
Whether a event is filtered by handler.
Definition: event.h:364
Definition: action.cpp:12
Key key() const
Normalized key event.
Definition: event.h:244
bool forward() const
If true, the key that produce character will commit a string.
Definition: event.h:303
Base class for fcitx event.
Definition: event.h:176
void setForward(bool forward)
It is designed for overriding the key forward option.
Definition: event.h:276
Enum type for input context capability.
Key rawKey() const
Key event after layout conversion.
Definition: event.h:292
Base class for User Interface addon.
bool accepted() const
Return value used by Instance::postEvent.
Definition: event.h:195
UserInterfaceComponent
Definition: userinterface.h:23
bool filtered() const override
Whether a event is filtered by handler.
Definition: event.h:489
void setKey(const Key &key)
It will automatically be called if input method layout does not match the system keyboard layout...
Definition: event.h:252
virtual bool filtered() const
Whether a event is filtered by handler.
Definition: event.h:205
Class provides bit flag support for Enum.
Definition: flags.h:33
An input context represents a client of Fcitx.
Definition: inputcontext.h:49
Class to represent a key.
Key normalize() const
Normalize a key, usually used when key is from frontend.
Definition: key.cpp:397