Fcitx
event.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_EVENT_H_
8 #define _FCITX_EVENT_H_
9 
10 #include <cstddef>
11 #include <cstdint>
12 #include <memory>
13 #include <string>
14 #include <utility>
16 #include <fcitx-utils/key.h>
17 #include <fcitx-utils/macros.h>
18 #include <fcitx/fcitxcore_export.h>
19 #include <fcitx/userinterface.h>
20 
21 /// \addtogroup FcitxCore
22 /// \{
23 /// \file
24 /// \brief Input Method event for Fcitx.
25 
26 namespace fcitx {
27 
28 class InputContext;
29 class FocusGroup;
30 
31 enum class ResetReason {
32  ChangeByInactivate FCITXCORE_DEPRECATED,
33  LostFocus FCITXCORE_DEPRECATED,
34  SwitchIM FCITXCORE_DEPRECATED,
35  Client
36 };
37 
38 /**
39  * The reason why input method is switched to another.
40  */
42  /// Switched by trigger key
43  Trigger,
44  /// Switched by deactivate key
45  Deactivate,
46  /// Switched by alternative trigger key
47  AltTrigger,
48  /// Switched by activate key
49  Activate,
50  /// Switched by enumerate key
51  Enumerate,
52  /// Switched by group change
54  /// Switched by capability change (e.g. password field)
56  /// miscellaneous reason
57  Other,
58 };
59 
60 enum class InputMethodMode { PhysicalKeyboard, OnScreenKeyboard };
61 
62 /**
63  * Type of input method events.
64  */
65 enum class EventType : uint32_t {
66  EventTypeFlag = 0xfffff000,
67  UserTypeFlag = 0xffff0000,
68  // send by frontend, captured by core, input method, or module
69  InputContextEventFlag = 0x0001000,
70  // send by im, captured by frontend, or module
71  InputMethodEventFlag = 0x0002000,
72 
73  /**
74  * captured by everything
75  */
76  InstanceEventFlag = 0x0003000,
77  InputContextCreated = InputContextEventFlag | 0x1,
78  InputContextDestroyed = InputContextEventFlag | 0x2,
79  /**
80  * FocusInEvent is generated when client gets focused.
81  *
82  * @see FocusInEvent
83  */
84  InputContextFocusIn = InputContextEventFlag | 0x3,
85  /**
86  * when using lost focus
87  * this might be variance case to case. the default behavior is to commit
88  * the preedit, and resetIM.
89  *
90  * Controlled by [Output/DontCommitPreeditWhenUnfocus], this option will not
91  * work for application switch doesn't support async commit.
92  *
93  * So OnClose is called when preedit IS committed (not like
94  * CChangeByInactivate,
95  * this behavior cannot be overridden), it give im a chance to choose
96  * remember this
97  * word or not.
98  *
99  * Input method need to notice, that the commit is already DONE, do not do
100  * extra commit.
101  *
102  * @see FocusOutEvent
103  */
104  InputContextFocusOut = InputContextEventFlag | 0x4,
105  /**
106  * Key event is generated when client press or release a key.
107  * @see KeyEvent
108  */
109  InputContextKeyEvent = InputContextEventFlag | 0x5,
110  /**
111  * ResetEvent is generated
112  *
113  */
114  InputContextReset = InputContextEventFlag | 0x6,
115  InputContextSurroundingTextUpdated = InputContextEventFlag | 0x7,
116  InputContextCapabilityChanged = InputContextEventFlag | 0x8,
117  InputContextCursorRectChanged = InputContextEventFlag | 0x9,
118  InputContextCapabilityAboutToChange = InputContextEventFlag | 0xD,
119  /**
120  * when user switch to a different input method by hand
121  * such as ctrl+shift by default, or by ui,
122  * default behavior is reset IM.
123  */
124  InputContextSwitchInputMethod = InputContextEventFlag | 0xA,
125 
126  // Two convenient event after input method is actually activate and
127  // deactivated. Useful for UI to update after specific input method get
128  // activated and deactivated. Will not be emitted if the input method is not
129  // a valid one.
130  InputContextInputMethodActivated = InputContextEventFlag | 0xB,
131  InputContextInputMethodDeactivated = InputContextEventFlag | 0xC,
132  /**
133  * InvokeAction event is generated when client click on the preedit.
134  *
135  * Not all client support this feature.
136  *
137  * @since 5.0.11
138  */
139  InputContextInvokeAction = InputContextEventFlag | 0xE,
140 
141  InputContextVirtualKeyboardEvent = InputContextEventFlag | 0xF,
142 
143  InputContextForwardKey = InputMethodEventFlag | 0x1,
144  InputContextCommitString = InputMethodEventFlag | 0x2,
145  InputContextDeleteSurroundingText = InputMethodEventFlag | 0x3,
146  InputContextUpdatePreedit = InputMethodEventFlag | 0x4,
147  InputContextUpdateUI = InputMethodEventFlag | 0x5,
148  InputContextCommitStringWithCursor = InputMethodEventFlag | 0x6,
149  InputContextFlushUI = InputMethodEventFlag | 0x7,
150 
151  /**
152  * This is generated when input method group changed.
153  * This would also trigger InputContextSwitchInputMethod afterwards.
154  */
156  /**
157  * InputMethodGroupAboutToChangeEvent is generated when input method group
158  * is about to be changed.
159  *
160  * @see InputMethodGroupAboutToChange
161  */
163  /**
164  * UIChangedEvent is posted when the UI implementation is changed.
165  */
167  /**
168  * CheckUpdateEvent is posted when the Instance is requested to check for
169  * newly installed addons and input methods.
170  *
171  * This can be used for addons to pick up new input methods if it provides
172  * input method at runtime.
173  */
175  /**
176  * FocusGroupFocusChanged is posted when a focus group changed its focused
177  * input context.
178  *
179  * This is a more fine grained control over focus in and focus out event.
180  * This is more useful for UI to keep track of what input context is being
181  * focused.
182  *
183  * @see FocusInEvent
184  * @see FocusOutEvent
185  */
187  /**
188  * Input method mode changed
189  */
191  /**
192  * Global config is reloaded
193  *
194  * This only fires after fcitx has entered running state.
195  * The initial load will not trigger this event.
196  * @see GlobalConfig
197  * @since 5.1.0
198  */
200  /**
201  * Virtual keyboard visibility changed
202  *
203  * @see UserInterfaceManager
204  * @since 5.1.0
205  */
207 };
208 
209 /**
210  * Base class for fcitx event.
211  */
212 class FCITXCORE_EXPORT Event {
213 public:
214  Event(EventType type) : type_(type) {}
215  virtual ~Event();
216 
217  /**
218  * Type of event, can be used to decide event class.
219  *
220  * @return fcitx::EventType
221  */
222  EventType type() const { return type_; }
223 
224  void accept() { accepted_ = true; }
225  /**
226  * Return value used by Instance::postEvent.
227  *
228  * @see Instance::postEvent
229  * @return bool
230  */
231  bool accepted() const { return accepted_; }
232 
233  /**
234  * Whether a event is filtered by handler.
235  *
236  * If event is filtered, it will not send to another handler.
237  * For now only keyevent from input context can be filtered.
238  *
239  * @return bool
240  */
241  virtual bool filtered() const { return false; }
242 
243  /**
244  * A helper function to check if a event is input context event.
245  *
246  * @return bool
247  */
248  bool isInputContextEvent() const {
249  auto flag = static_cast<uint32_t>(EventType::InputContextEventFlag);
250  auto mask = static_cast<uint32_t>(EventType::EventTypeFlag);
251  return (static_cast<uint32_t>(type_) & mask) == flag;
252  }
253 
254 protected:
255  EventType type_;
256  bool accepted_ = false;
257 };
258 
259 class FCITXCORE_EXPORT InputContextEvent : public Event {
260 public:
262  : Event(type), ic_(context) {}
263 
264  InputContext *inputContext() const { return ic_; }
265 
266 protected:
267  InputContext *ic_;
268 };
269 
270 class FCITXCORE_EXPORT KeyEventBase : public InputContextEvent {
271 public:
272  KeyEventBase(EventType type, InputContext *context, Key rawKey,
273  bool isRelease = false, int time = 0);
274  KeyEventBase(const KeyEventBase &) = default;
275 
276  /**
277  * Normalized key event.
278  *
279  * @return fcitx::Key
280  */
281  Key key() const { return key_; }
282 
283  /**
284  * It will automatically be called if input method layout does not match the
285  * system keyboard layout.
286  *
287  * @param key p_key:...
288  */
289  void setKey(const Key &key) {
290  key_ = key;
291  forward_ = true;
292  }
293 
294  /**
295  * It is designed for faking the key event. Normally should not be used.
296  *
297  * @param key key event to override.
298  * @since 5.0.4
299  */
300  void setRawKey(const Key &key) {
301  rawKey_ = key;
302  key_ = key.normalize();
303  forward_ = true;
304  }
305 
306  /**
307  * It is designed for overriding the key forward option. Normally should not
308  * be used.
309  *
310  * @param forward
311  * @since 5.0.4
312  */
313  void setForward(bool forward) { forward_ = forward; }
314 
315  /**
316  * Key event regardless of keyboard layout conversion.
317  *
318  * @return fcitx::Key
319  */
320  Key origKey() const { return origKey_; }
321 
322  /**
323  * Key event after layout conversion.
324  *
325  * Basically it is the "unnormalized" key event.
326  *
327  * @return fcitx::Key
328  */
329  Key rawKey() const { return rawKey_; }
330  bool isRelease() const { return isRelease_; }
331  int time() const { return time_; }
332 
333  /**
334  * If true, the key that produce character will commit a string.
335  *
336  * This is currently used by internal keyboard layout translation.
337  *
338  * @return bool
339  */
340  bool forward() const { return forward_; }
341 
342  /**
343  * Whether this key event is derived from a virtual keyboard
344  *
345  * @return bool
346  * @since 5.1.2
347  */
348  bool isVirtual() const { return origKey_.isVirtual(); }
349 
350 protected:
351  Key key_, origKey_, rawKey_;
352  bool isRelease_;
353  int time_;
354  bool forward_ = false;
355 };
356 
357 class FCITXCORE_EXPORT KeyEvent : public KeyEventBase {
358 public:
359  KeyEvent(InputContext *context, Key rawKey, bool isRelease = false,
360  int time = 0)
362  isRelease, time) {}
363 
364  void filter() { filtered_ = true; }
365  bool filtered() const override { return filtered_; }
366  void filterAndAccept() {
367  filter();
368  accept();
369  }
370 
371 private:
372  bool filtered_ = false;
373 };
374 
376 
377 class FCITXCORE_EXPORT VirtualKeyboardEvent : public InputContextEvent {
378 public:
379  VirtualKeyboardEvent(InputContext *context, bool isRelease, int time = 0);
381 
382  int time() const;
383 
384  void setKey(Key key);
385  const Key &key() const;
386 
387  void setPosition(float x, float y);
388  float x() const;
389  float y() const;
390 
391  void setLongPress(bool longPress);
392  bool isLongPress() const;
393 
394  void setUserAction(uint64_t actionId);
395  uint64_t userAction() const;
396 
397  void setText(std::string text);
398  const std::string &text() const;
399 
400  std::unique_ptr<KeyEvent> toKeyEvent() const;
401 
402 protected:
403  FCITX_DECLARE_PRIVATE(VirtualKeyboardEvent);
404  std::unique_ptr<VirtualKeyboardEventPrivate> d_ptr;
405 };
406 
407 class FCITXCORE_EXPORT ForwardKeyEvent : public KeyEventBase {
408 public:
409  ForwardKeyEvent(InputContext *context, Key rawKey, bool isRelease = false,
410  int time = 0)
411  : KeyEventBase(EventType::InputContextForwardKey, context, rawKey,
412  isRelease, time) {}
413 };
414 
415 class FCITXCORE_EXPORT CommitStringEvent : public InputContextEvent {
416 public:
417  CommitStringEvent(const std::string &text, InputContext *context)
418  : InputContextEvent(context, EventType::InputContextCommitString),
419  text_(text) {}
420 
421  const std::string &text() const { return text_; }
422 
423 protected:
424  std::string text_;
425 };
426 
427 /**
428  * Event for commit string with cursor
429  *
430  * @see InputContext::commitStringWithCursor
431  * @since 5.1.2
432  */
433 class FCITXCORE_EXPORT CommitStringWithCursorEvent : public InputContextEvent {
434 public:
435  CommitStringWithCursorEvent(std::string text, size_t cursor,
436  InputContext *context)
437  : InputContextEvent(context,
438  EventType::InputContextCommitStringWithCursor),
439  text_(std::move(text)), cursor_(cursor) {}
440 
441  const std::string &text() const { return text_; }
442  size_t cursor() const { return cursor_; }
443 
444 protected:
445  std::string text_;
446  size_t cursor_;
447 };
448 
449 class FCITXCORE_EXPORT InvokeActionEvent : public InputContextEvent {
450 public:
451  enum class Action { LeftClick, RightClick };
452  InvokeActionEvent(Action action, int cursor, InputContext *context)
454  action_(action), cursor_(cursor) {}
455 
456  Action action() const { return action_; }
457  int cursor() const { return cursor_; }
458 
459  void filter() {
460  filtered_ = true;
461  accept();
462  }
463  bool filtered() const override { return filtered_; }
464 
465 protected:
466  Action action_;
467  int cursor_;
468  bool filtered_ = false;
469 };
470 
472  : public InputContextEvent {
473 public:
475  const std::string &oldIM,
476  InputContext *context)
478  reason_(reason), oldInputMethod_(oldIM) {}
479 
480  InputMethodSwitchedReason reason() const { return reason_; }
481  const std::string &oldInputMethod() const { return oldInputMethod_; }
482 
483 protected:
485  std::string oldInputMethod_;
486 };
487 
488 class FCITXCORE_EXPORT ResetEvent : public InputContextEvent {
489 public:
490  FCITXCORE_DEPRECATED ResetEvent(ResetReason reason, InputContext *context)
492  reason_(reason) {}
493  ResetEvent(InputContext *context)
495  reason_(ResetReason::Client) {}
496 
497  FCITXCORE_DEPRECATED ResetReason reason() const { return reason_; }
498 
499 protected:
500  ResetReason reason_;
501 };
502 
503 class FCITXCORE_EXPORT InputContextUpdateUIEvent : public InputContextEvent {
504 public:
506  InputContext *context, bool immediate = false)
507  : InputContextEvent(context, EventType::InputContextUpdateUI),
508  component_(component), immediate_(immediate) {}
509 
510  UserInterfaceComponent component() const { return component_; }
511  bool immediate() const { return immediate_; }
512 
513 protected:
514  UserInterfaceComponent component_;
515  bool immediate_;
516 };
517 
518 /**
519  * Events triggered that user interface manager that flush the UI update.
520  *
521  * @since 5.1.2
522  */
523 class FCITXCORE_EXPORT InputContextFlushUIEvent : public InputContextEvent {
524 public:
526  InputContext *context)
527  : InputContextEvent(context, EventType::InputContextFlushUI),
528  component_(component) {}
529 
530  UserInterfaceComponent component() const { return component_; }
531 
532 protected:
533  UserInterfaceComponent component_;
534 };
535 
536 class FCITXCORE_EXPORT VirtualKeyboardVisibilityChangedEvent : public Event {
537 public:
540 };
541 
542 class FCITXCORE_EXPORT InputMethodNotificationEvent : public InputContextEvent {
543 public:
544  InputMethodNotificationEvent(EventType type, const std::string &name,
545  InputContext *context)
546  : InputContextEvent(context, type), name_(name) {}
547 
548  const std::string &name() const { return name_; }
549 
550 protected:
551  std::string name_;
552 };
553 
554 class FCITXCORE_EXPORT InputMethodActivatedEvent
556 public:
557  InputMethodActivatedEvent(const std::string &name, InputContext *context)
559  EventType::InputContextInputMethodActivated, name, context) {}
560 };
561 
562 class FCITXCORE_EXPORT InputMethodDeactivatedEvent
564 public:
565  InputMethodDeactivatedEvent(const std::string &name, InputContext *context)
567  EventType::InputContextInputMethodDeactivated, name, context) {}
568 };
569 
570 #define FCITX_DEFINE_SIMPLE_EVENT(NAME, TYPE, ARGS...) \
571  struct FCITXCORE_EXPORT NAME##Event : public InputContextEvent { \
572  NAME##Event(InputContext *ic) \
573  : InputContextEvent(ic, EventType::TYPE) {} \
574  }
575 
576 FCITX_DEFINE_SIMPLE_EVENT(InputContextCreated, InputContextCreated);
577 FCITX_DEFINE_SIMPLE_EVENT(InputContextDestroyed, InputContextDestroyed);
578 FCITX_DEFINE_SIMPLE_EVENT(FocusIn, InputContextFocusIn);
579 FCITX_DEFINE_SIMPLE_EVENT(FocusOut, InputContextFocusOut);
580 FCITX_DEFINE_SIMPLE_EVENT(SurroundingTextUpdated,
581  InputContextSurroundingTextUpdated);
582 FCITX_DEFINE_SIMPLE_EVENT(CursorRectChanged, InputContextCursorRectChanged);
583 FCITX_DEFINE_SIMPLE_EVENT(UpdatePreedit, InputContextUpdatePreedit);
584 
585 class FCITXCORE_EXPORT InputMethodGroupChangedEvent : public Event {
586 public:
589 };
590 
591 class FCITXCORE_EXPORT InputMethodGroupAboutToChangeEvent : public Event {
592 public:
595 };
596 
597 class FCITXCORE_EXPORT UIChangedEvent : public Event {
598 public:
600 };
601 
602 class FCITXCORE_EXPORT CheckUpdateEvent : public Event {
603 public:
605 
606  /// Make checking update short circuit. If anything need a refresh, just
607  /// simply break.
608  void setHasUpdate() {
609  filtered_ = true;
610  accept();
611  }
612  bool filtered() const override { return filtered_; }
613 
614 private:
615  bool filtered_ = false;
616 };
617 
618 /**
619  * Notify a focus change for focus group.
620  *
621  * @since 5.0.11
622  */
623 class FCITXCORE_EXPORT FocusGroupFocusChangedEvent : public Event {
624 public:
626  InputContext *newFocus)
627  : Event(EventType::FocusGroupFocusChanged), group_(group),
628  oldFocus_(oldFocus), newFocus_(newFocus) {}
629 
630  FocusGroup *group() const { return group_; }
631  InputContext *oldFocus() const { return oldFocus_; };
632  InputContext *newFocus() const { return newFocus_; };
633 
634 private:
635  FocusGroup *group_;
636  InputContext *oldFocus_;
637  InputContext *newFocus_;
638 };
639 
640 /**
641  * Notify the input method mode is changed.
642  *
643  * @see Instance::InputMethodMode
644  * @since 5.1.0
645  */
646 class FCITXCORE_EXPORT InputMethodModeChangedEvent : public Event {
647 public:
649 };
650 
651 /**
652  * Notify the global config is reloaded.
653  *
654  * @see GlobalConfig
655  * @since 5.1.0
656  */
657 class FCITXCORE_EXPORT GlobalConfigReloadedEvent : public Event {
658 public:
660 };
661 
662 class FCITXCORE_EXPORT CapabilityEvent : public InputContextEvent {
663 public:
665  CapabilityFlags newFlags)
666  : InputContextEvent(ic, type), oldFlags_(oldFlags),
667  newFlags_(newFlags) {}
668 
669  auto oldFlags() const { return oldFlags_; }
670  auto newFlags() const { return newFlags_; }
671 
672 protected:
673  const CapabilityFlags oldFlags_;
674  const CapabilityFlags newFlags_;
675 };
676 
677 class FCITXCORE_EXPORT CapabilityChangedEvent : public CapabilityEvent {
678 public:
680  CapabilityFlags newFlags)
681  : CapabilityEvent(ic, EventType::InputContextCapabilityChanged,
682  oldFlags, newFlags) {}
683 };
684 
685 class FCITXCORE_EXPORT CapabilityAboutToChangeEvent : public CapabilityEvent {
686 public:
688  CapabilityFlags newFlags)
689  : CapabilityEvent(ic, EventType::InputContextCapabilityAboutToChange,
690  oldFlags, newFlags) {}
691 };
692 
693 } // namespace fcitx
694 
695 #endif // _FCITX_EVENT_H_
InputMethodGroupAboutToChangeEvent is generated when input method group is about to be changed...
Describe a Key in fcitx.
Definition: key.h:41
bool accepted() const
Return value used by Instance::postEvent.
Definition: event.h:231
EventType
Type of input method events.
Definition: event.h:65
Switched by alternative trigger key.
void setHasUpdate()
Make checking update short circuit.
Definition: event.h:608
ResetEvent is generated.
FocusInEvent is generated when client gets focused.
Notify a focus change for focus group.
Definition: event.h:623
This is generated when input method group changed.
when user switch to a different input method by hand such as ctrl+shift by default, or by ui, default behavior is reset IM.
InputMethodSwitchedReason
The reason why input method is switched to another.
Definition: event.h:41
Definition: action.cpp:17
void setKey(const Key &key)
It will automatically be called if input method layout does not match the system keyboard layout...
Definition: event.h:289
Key key() const
Normalized key event.
Definition: event.h:281
bool isVirtual() const
Whether this key event is derived from a virtual keyboard.
Definition: event.h:348
virtual bool filtered() const
Whether a event is filtered by handler.
Definition: event.h:241
bool filtered() const override
Whether a event is filtered by handler.
Definition: event.h:365
Base class for fcitx event.
Definition: event.h:212
Virtual keyboard visibility changed.
Enum type for input context capability.
Switched by capability change (e.g. password field)
Base class for User Interface addon.
Global config is reloaded.
Events triggered that user interface manager that flush the UI update.
Definition: event.h:523
InvokeAction event is generated when client click on the preedit.
bool filtered() const override
Whether a event is filtered by handler.
Definition: event.h:612
FocusGroupFocusChanged is posted when a focus group changed its focused input context.
UserInterfaceComponent
Definition: userinterface.h:21
Key rawKey() const
Key event after layout conversion.
Definition: event.h:329
Notify the input method mode is changed.
Definition: event.h:646
CheckUpdateEvent is posted when the Instance is requested to check for newly installed addons and inp...
Input method mode changed.
bool filtered() const override
Whether a event is filtered by handler.
Definition: event.h:463
bool isInputContextEvent() const
A helper function to check if a event is input context event.
Definition: event.h:248
UIChangedEvent is posted when the UI implementation is changed.
Key origKey() const
Key event regardless of keyboard layout conversion.
Definition: event.h:320
Class provides bit flag support for Enum.
Definition: flags.h:33
Event for commit string with cursor.
Definition: event.h:433
EventType type() const
Type of event, can be used to decide event class.
Definition: event.h:222
An input context represents a client of Fcitx.
Definition: inputcontext.h:47
Key event is generated when client press or release a key.
Class to represent a key.
void setRawKey(const Key &key)
It is designed for faking the key event.
Definition: event.h:300
bool forward() const
If true, the key that produce character will commit a string.
Definition: event.h:340
void setForward(bool forward)
It is designed for overriding the key forward option.
Definition: event.h:313
Notify the global config is reloaded.
Definition: event.h:657
when using lost focus this might be variance case to case.
Key normalize() const
Normalize a key, usually used when key is from frontend.
Definition: key.cpp:495