Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / widget / gtk / IMContextWrapper.h
blobcf1d2638e0f41aee3c0e03e22af0d344986788ee
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #ifndef IMContextWrapper_h_
9 #define IMContextWrapper_h_
11 #include <gdk/gdk.h>
12 #include <gtk/gtk.h>
14 #include "nsString.h"
15 #include "nsCOMPtr.h"
16 #include "nsTArray.h"
17 #include "nsIWidget.h"
18 #include "mozilla/CheckedInt.h"
19 #include "mozilla/ContentData.h"
20 #include "mozilla/EventForwards.h"
21 #include "mozilla/Maybe.h"
22 #include "mozilla/TextEventDispatcherListener.h"
23 #include "mozilla/WritingModes.h"
24 #include "mozilla/GUniquePtr.h"
25 #include "mozilla/widget/IMEData.h"
27 class nsWindow;
29 namespace mozilla {
30 namespace widget {
32 /**
33 * KeyHandlingState is result of IMContextWrapper::OnKeyEvent().
35 enum class KeyHandlingState {
36 // The native key event has not been handled by IMContextWrapper.
37 eNotHandled,
38 // The native key event was handled by IMContextWrapper.
39 eHandled,
40 // The native key event has not been handled by IMContextWrapper,
41 // but eKeyDown or eKeyUp event has been dispatched.
42 eNotHandledButEventDispatched,
43 // The native key event has not been handled by IMContextWrapper,
44 // but eKeyDown or eKeyUp event has been dispatched and consumed.
45 eNotHandledButEventConsumed,
48 class IMContextWrapper final : public TextEventDispatcherListener {
49 public:
50 // TextEventDispatcherListener implementation
51 NS_DECL_ISUPPORTS
53 NS_IMETHOD NotifyIME(TextEventDispatcher* aTextEventDispatcher,
54 const IMENotification& aNotification) override;
55 NS_IMETHOD_(IMENotificationRequests) GetIMENotificationRequests() override;
56 NS_IMETHOD_(void)
57 OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) override;
58 NS_IMETHOD_(void)
59 WillDispatchKeyboardEvent(TextEventDispatcher* aTextEventDispatcher,
60 WidgetKeyboardEvent& aKeyboardEvent,
61 uint32_t aIndexOfKeypress, void* aData) override;
63 public:
64 // aOwnerWindow is a pointer of the owner window. When aOwnerWindow is
65 // destroyed, the related IME contexts are released (i.e., IME cannot be
66 // used with the instance after that).
67 explicit IMContextWrapper(nsWindow* aOwnerWindow);
69 // Called when the process is being shut down.
70 static void Shutdown();
72 // "Enabled" means the users can use all IMEs.
73 // I.e., the focus is in the normal editors.
74 bool IsEnabled() const;
76 // OnFocusWindow is a notification that aWindow is going to be focused.
77 void OnFocusWindow(nsWindow* aWindow);
78 // OnBlurWindow is a notification that aWindow is going to be unfocused.
79 void OnBlurWindow(nsWindow* aWindow);
80 // OnDestroyWindow is a notification that aWindow is going to be destroyed.
81 void OnDestroyWindow(nsWindow* aWindow);
82 // OnFocusChangeInGecko is a notification that an editor gets focus.
83 void OnFocusChangeInGecko(bool aFocus);
84 // OnSelectionChange is a notification that selection (caret) is changed
85 // in the focused editor.
86 void OnSelectionChange(nsWindow* aCaller,
87 const IMENotification& aIMENotification);
88 // OnThemeChanged is called when desktop theme is changed.
89 static void OnThemeChanged();
91 /**
92 * OnKeyEvent() is called when aWindow gets a native key press event or a
93 * native key release event. If this returns true, the key event was
94 * filtered by IME. Otherwise, this returns false.
95 * NOTE: When the native key press event starts composition, this returns
96 * true but dispatches an eKeyDown event or eKeyUp event before
97 * dispatching composition events or content command event.
99 * @param aWindow A window on which user operate the
100 * key.
101 * @param aEvent A native key press or release
102 * event.
103 * @param aKeyboardEventWasDispatched true if eKeyDown or eKeyUp event
104 * for aEvent has already been
105 * dispatched. In this case,
106 * this class doesn't dispatch
107 * keyboard event anymore.
109 KeyHandlingState OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent,
110 bool aKeyboardEventWasDispatched = false);
112 // IME related nsIWidget methods.
113 nsresult EndIMEComposition(nsWindow* aCaller);
114 void SetInputContext(nsWindow* aCaller, const InputContext* aContext,
115 const InputContextAction* aAction);
116 InputContext GetInputContext();
117 void OnUpdateComposition();
118 void OnLayoutChange();
120 TextEventDispatcher* GetTextEventDispatcher();
122 // TODO: Typically, new IM comes every several years. And now, our code
123 // becomes really IM behavior dependent. So, perhaps, we need prefs
124 // to control related flags for IM developers.
125 enum class IMContextID : uint8_t {
126 Fcitx, // 4.x or earlier
127 Fcitx5,
128 IBus,
129 IIIMF,
130 Scim,
131 Uim,
132 Wayland,
133 Unknown,
136 friend std::ostream& operator<<(std::ostream& aStream,
137 const IMContextID& aIMContextID) {
138 switch (aIMContextID) {
139 case IMContextID::Fcitx:
140 return aStream << "Fcitx";
141 case IMContextID::Fcitx5:
142 return aStream << "Fcitx5";
143 case IMContextID::IBus:
144 return aStream << "IBus";
145 case IMContextID::IIIMF:
146 return aStream << "IIIMF";
147 case IMContextID::Scim:
148 return aStream << "Scim";
149 case IMContextID::Uim:
150 return aStream << "Uim";
151 case IMContextID::Wayland:
152 return aStream << "Wayland";
153 case IMContextID::Unknown:
154 return aStream << "Unknown";
156 MOZ_ASSERT_UNREACHABLE("Add new case for the new IM support");
157 return aStream << "Unknown";
161 * GetIMName() returns IM name associated with mContext. If the context is
162 * xim, this look for actual engine from XMODIFIERS environment variable.
164 nsDependentCSubstring GetIMName() const;
167 * GetWaitingSynthesizedKeyPressHardwareKeyCode() returns hardware_keycode
168 * value of last handled GDK_KEY_PRESS event which is probable handled by
169 * IME asynchronously and we have not received synthesized GDK_KEY_PRESS
170 * event yet.
172 static guint16 GetWaitingSynthesizedKeyPressHardwareKeyCode() {
173 return sWaitingSynthesizedKeyPressHardwareKeyCode;
176 protected:
177 ~IMContextWrapper();
180 * SetInputPurposeAndInputHints() sets input-purpose and input-hints of
181 * current IM context to the values computed with mInputContext.
183 void SetInputPurposeAndInputHints();
185 // Owner of an instance of this class. This should be top level window.
186 // The owner window must release the contexts when it's destroyed because
187 // the IME contexts need the native window. If OnDestroyWindow() is called
188 // with the owner window, it'll release IME contexts. Otherwise, it'll
189 // just clean up any existing composition if it's related to the destroying
190 // child window.
191 nsWindow* mOwnerWindow;
193 // A last focused window in this class's context.
194 nsWindow* mLastFocusedWindow;
196 // Actual context. This is used for handling the user's input.
197 GtkIMContext* mContext;
199 // mSimpleContext is used for the password field and
200 // the |ime-mode: disabled;| editors if sUseSimpleContext is true.
201 // These editors disable IME. But dead keys should work. Fortunately,
202 // the simple IM context of GTK2 support only them.
203 GtkIMContext* mSimpleContext;
205 // mDummyContext is a dummy context and will be used in Focus()
206 // when the state of mEnabled means disabled. This context's IME state is
207 // always "closed", so it closes IME forcedly.
208 GtkIMContext* mDummyContext;
210 // mComposingContext is not nullptr while one of mContext, mSimpleContext
211 // and mDummyContext has composition.
212 // XXX: We don't assume that two or more context have composition same time.
213 GtkIMContext* mComposingContext;
215 // IME enabled state and other things defined in InputContext.
216 // Use following helper methods if you don't need the detail of the status.
217 InputContext mInputContext;
219 // mCompositionStart is the start offset of the composition string in the
220 // current content. When <textarea> or <input> have focus, it means offset
221 // from the first character of them. When a HTML editor has focus, it
222 // means offset from the first character of the root element of the editor.
223 uint32_t mCompositionStart;
225 // mDispatchedCompositionString is the latest composition string which
226 // was dispatched by compositionupdate event.
227 nsString mDispatchedCompositionString;
229 // mSelectedStringRemovedByComposition is the selected string which was
230 // removed by first compositionchange event.
231 nsString mSelectedStringRemovedByComposition;
233 // OnKeyEvent() temporarily sets mProcessingKeyEvent to the given native
234 // event.
235 GdkEventKey* mProcessingKeyEvent;
238 * GdkEventKeyQueue stores *copy* of GdkEventKey instances. However, this
239 * must be safe to our usecase since it has |time| and the value should not
240 * be same as older event.
242 class GdkEventKeyQueue final {
243 public:
244 ~GdkEventKeyQueue() { Clear(); }
246 void Clear() { mEvents.Clear(); }
249 * PutEvent() puts new event into the queue.
251 void PutEvent(const GdkEventKey* aEvent) {
252 GdkEventKey* newEvent = reinterpret_cast<GdkEventKey*>(
253 gdk_event_copy(reinterpret_cast<const GdkEvent*>(aEvent)));
254 newEvent->state &= GDK_MODIFIER_MASK;
255 mEvents.AppendElement(newEvent);
259 * RemoveEvent() removes oldest same event and its preceding events
260 * from the queue.
262 void RemoveEvent(const GdkEventKey* aEvent) {
263 size_t index = IndexOf(aEvent);
264 if (NS_WARN_IF(index == GdkEventKeyQueue::NoIndex())) {
265 return;
267 mEvents.RemoveElementAt(index);
271 * Return corresponding GDK_KEY_PRESS event for aEvent. aEvent must be a
272 * GDK_KEY_RELEASE event.
274 const GdkEventKey* GetCorrespondingKeyPressEvent(
275 const GdkEventKey* aEvent) const {
276 MOZ_ASSERT(aEvent->type == GDK_KEY_RELEASE);
277 for (const GUniquePtr<GdkEventKey>& pendingKeyEvent : mEvents) {
278 if (pendingKeyEvent->type == GDK_KEY_PRESS &&
279 aEvent->hardware_keycode == pendingKeyEvent->hardware_keycode) {
280 return pendingKeyEvent.get();
283 return nullptr;
287 * FirstEvent() returns oldest event in the queue.
289 GdkEventKey* GetFirstEvent() const {
290 if (mEvents.IsEmpty()) {
291 return nullptr;
293 return mEvents[0].get();
296 bool IsEmpty() const { return mEvents.IsEmpty(); }
298 static size_t NoIndex() { return nsTArray<GdkEventKey*>::NoIndex; }
299 size_t Length() const { return mEvents.Length(); }
300 size_t IndexOf(const GdkEventKey* aEvent) const {
301 static_assert(!(GDK_MODIFIER_MASK & (1 << 24)),
302 "We assumes 25th bit is used by some IM, but used by GDK");
303 static_assert(!(GDK_MODIFIER_MASK & (1 << 25)),
304 "We assumes 26th bit is used by some IM, but used by GDK");
305 for (size_t i = 0; i < mEvents.Length(); i++) {
306 GdkEventKey* event = mEvents[i].get();
307 // It must be enough to compare only type, time, keyval and
308 // part of state. Note that we cannot compaire two events
309 // simply since IME may have changed unused bits of state.
310 if (event->time == aEvent->time) {
311 if (NS_WARN_IF(event->type != aEvent->type) ||
312 NS_WARN_IF(event->keyval != aEvent->keyval) ||
313 NS_WARN_IF(event->state != (aEvent->state & GDK_MODIFIER_MASK))) {
314 continue;
317 return i;
319 return GdkEventKeyQueue::NoIndex();
322 private:
323 nsTArray<GUniquePtr<GdkEventKey>> mEvents;
325 // OnKeyEvent() append mPostingKeyEvents when it believes that a key event
326 // is posted to other IME process.
327 GdkEventKeyQueue mPostingKeyEvents;
329 static guint16 sWaitingSynthesizedKeyPressHardwareKeyCode;
331 struct Range {
332 uint32_t mOffset;
333 uint32_t mLength;
335 Range() : mOffset(UINT32_MAX), mLength(UINT32_MAX) {}
337 bool IsValid() const { return mOffset != UINT32_MAX; }
338 void Clear() {
339 mOffset = UINT32_MAX;
340 mLength = UINT32_MAX;
344 // current target offset and length of IME composition
345 Range mCompositionTargetRange;
347 // mCompositionState indicates current status of composition.
348 enum eCompositionState : uint8_t {
349 eCompositionState_NotComposing,
350 eCompositionState_CompositionStartDispatched,
351 eCompositionState_CompositionChangeEventDispatched
353 eCompositionState mCompositionState;
355 bool IsComposing() const {
356 return (mCompositionState != eCompositionState_NotComposing);
359 bool IsComposingOn(GtkIMContext* aContext) const {
360 return IsComposing() && mComposingContext == aContext;
363 bool IsComposingOnCurrentContext() const {
364 return IsComposingOn(GetCurrentContext());
367 bool EditorHasCompositionString() {
368 return (mCompositionState ==
369 eCompositionState_CompositionChangeEventDispatched);
373 * Checks if aContext is valid context for handling composition.
375 * @param aContext An IM context which is specified by native
376 * composition events.
377 * @return true if the context is valid context for
378 * handling composition. Otherwise, false.
380 bool IsValidContext(GtkIMContext* aContext) const;
382 const char* GetCompositionStateName() {
383 switch (mCompositionState) {
384 case eCompositionState_NotComposing:
385 return "NotComposing";
386 case eCompositionState_CompositionStartDispatched:
387 return "CompositionStartDispatched";
388 case eCompositionState_CompositionChangeEventDispatched:
389 return "CompositionChangeEventDispatched";
390 default:
391 return "InvaildState";
395 // mIMContextID indicates the ID of mContext. This is actually indicates
396 // IM which user selected.
397 IMContextID mIMContextID;
399 // If mContentSelection is Nothing, it means that
400 // EnsureToCacheContentSelection failed to get selection or just not caching
401 // the selection.
402 Maybe<ContentSelection> mContentSelection;
405 * Return true if mContentSelection is set to some. Otherwise, false.
407 bool EnsureToCacheContentSelection(nsAString* aSelectedString = nullptr);
409 enum class IMEFocusState : uint8_t {
410 // IME has focus
411 Focused,
412 // IME was blurred
413 Blurred,
414 // IME was blurred without a focus change
415 BlurredWithoutFocusChange,
417 friend std::ostream& operator<<(std::ostream& aStream, IMEFocusState aState) {
418 switch (aState) {
419 case IMEFocusState::Focused:
420 return aStream << "IMEFocusState::Focused";
421 case IMEFocusState::Blurred:
422 return aStream << "IMEFocusState::Blurred";
423 case IMEFocusState::BlurredWithoutFocusChange:
424 return aStream << "IMEFocusState::BlurredWithoutFocusChange";
425 default:
426 MOZ_ASSERT_UNREACHABLE("Invalid value");
427 return aStream << "<illegal value>";
430 IMEFocusState mIMEFocusState = IMEFocusState::Blurred;
432 // mFallbackToKeyEvent is set to false when this class starts to handle
433 // a native key event (at that time, mProcessingKeyEvent is set to the
434 // native event). If active IME just commits composition with a character
435 // which is produced by the key with current keyboard layout, this is set
436 // to true.
437 bool mFallbackToKeyEvent;
438 // mKeyboardEventWasDispatched is used by OnKeyEvent() and
439 // MaybeDispatchKeyEventAsProcessedByIME().
440 // MaybeDispatchKeyEventAsProcessedByIME() dispatches an eKeyDown or
441 // eKeyUp event event if the composition is caused by a native
442 // key press event. If this is true, a keyboard event has been dispatched
443 // for the native event. If so, MaybeDispatchKeyEventAsProcessedByIME()
444 // won't dispatch keyboard event anymore.
445 bool mKeyboardEventWasDispatched;
446 // Whether the keyboard event which as dispatched at setting
447 // mKeyboardEventWasDispatched to true was consumed or not.
448 bool mKeyboardEventWasConsumed;
449 // mIsDeletingSurrounding is true while OnDeleteSurroundingNative() is
450 // trying to delete the surrounding text.
451 bool mIsDeletingSurrounding;
452 // mLayoutChanged is true after OnLayoutChange() is called. This is reset
453 // when eCompositionChange is being dispatched.
454 bool mLayoutChanged;
455 // mSetCursorPositionOnKeyEvent true when caret rect or position is updated
456 // with no composition. If true, we update candidate window position
457 // before key down
458 bool mSetCursorPositionOnKeyEvent;
459 // mPendingResettingIMContext becomes true if selection change notification
460 // is received during composition but the selection change occurred before
461 // starting the composition. In such case, we cannot notify IME of
462 // selection change during composition because we don't want to commit
463 // the composition in such case. However, we should notify IME of the
464 // selection change after the composition is committed.
465 bool mPendingResettingIMContext;
466 // mRetrieveSurroundingSignalReceived is true after "retrieve_surrounding"
467 // signal is received until selection is changed in Gecko.
468 bool mRetrieveSurroundingSignalReceived;
469 // mMaybeInDeadKeySequence is set to true when we detect a dead key press
470 // and set to false when we're sure dead key sequence has been finished.
471 // Note that we cannot detect which key event causes ending a dead key
472 // sequence. For example, when you press dead key grave with ibus Spanish
473 // keyboard layout, it just consumes the key event when we call
474 // gtk_im_context_filter_keypress(). Then, pressing "Escape" key cancels
475 // the dead key sequence but we don't receive any signal and it's consumed
476 // by gtk_im_context_filter_keypress() normally. On the other hand, when
477 // pressing "Shift" key causes exactly same behavior but dead key sequence
478 // isn't finished yet.
479 bool mMaybeInDeadKeySequence;
480 // mIsIMInAsyncKeyHandlingMode is set to true if we know that IM handles
481 // key events asynchronously. I.e., filtered key event may come again
482 // later.
483 bool mIsIMInAsyncKeyHandlingMode;
484 // mIsKeySnooped is set to true if IM uses key snooper to listen key events.
485 // In such case, we won't receive key events if IME consumes the event.
486 bool mIsKeySnooped;
487 // mSetInputPurposeAndInputHints is set if `SetInputContext` wants `Focus`
488 // to set input-purpose and input-hints.
489 bool mSetInputPurposeAndInputHints;
491 // sLastFocusedContext is a pointer to the last focused instance of this
492 // class. When a instance is destroyed and sLastFocusedContext refers it,
493 // this is cleared. So, this refers valid pointer always.
494 static IMContextWrapper* sLastFocusedContext;
496 // sUseSimpleContext indeicates if password editors and editors with
497 // |ime-mode: disabled;| should use GtkIMContextSimple.
498 // If true, they use GtkIMContextSimple. Otherwise, not.
499 static bool sUseSimpleContext;
501 // Callback methods for native IME events. These methods should call
502 // the related instance methods simply.
503 static gboolean OnRetrieveSurroundingCallback(GtkIMContext* aContext,
504 IMContextWrapper* aModule);
505 static gboolean OnDeleteSurroundingCallback(GtkIMContext* aContext,
506 gint aOffset, gint aNChars,
507 IMContextWrapper* aModule);
508 static void OnCommitCompositionCallback(GtkIMContext* aContext,
509 const gchar* aString,
510 IMContextWrapper* aModule);
511 static void OnChangeCompositionCallback(GtkIMContext* aContext,
512 IMContextWrapper* aModule);
513 static void OnStartCompositionCallback(GtkIMContext* aContext,
514 IMContextWrapper* aModule);
515 static void OnEndCompositionCallback(GtkIMContext* aContext,
516 IMContextWrapper* aModule);
518 // The instance methods for the native IME events.
519 gboolean OnRetrieveSurroundingNative(GtkIMContext* aContext);
520 gboolean OnDeleteSurroundingNative(GtkIMContext* aContext, gint aOffset,
521 gint aNChars);
522 void OnCommitCompositionNative(GtkIMContext* aContext, const gchar* aString);
523 void OnChangeCompositionNative(GtkIMContext* aContext);
524 void OnStartCompositionNative(GtkIMContext* aContext);
525 void OnEndCompositionNative(GtkIMContext* aContext);
528 * GetCurrentContext() returns current IM context which is chosen with the
529 * enabled state.
530 * WARNING:
531 * When this class receives some signals for a composition after focus
532 * is moved in Gecko, the result of this may be different from given
533 * context by the signals.
535 GtkIMContext* GetCurrentContext() const;
538 * GetActiveContext() returns a composing context or current context.
540 GtkIMContext* GetActiveContext() const {
541 return mComposingContext ? mComposingContext : GetCurrentContext();
544 // If the owner window and IM context have been destroyed, returns TRUE.
545 bool IsDestroyed() { return !mOwnerWindow; }
547 void NotifyIMEOfFocusChange(IMEFocusState aIMEFocusState);
549 // Initializes the instance.
550 void Init();
553 * Reset the active context, i.e., if there is mComposingContext, reset it.
554 * Otherwise, reset current context. Note that all native composition
555 * events during calling this will be ignored.
557 void ResetIME();
559 // Gets the current composition string by the native APIs.
560 void GetCompositionString(GtkIMContext* aContext,
561 nsAString& aCompositionString);
564 * Generates our text range array from current composition string.
566 * @param aContext A GtkIMContext which is being handled.
567 * @param aCompositionString The data to be dispatched with
568 * compositionchange event.
570 already_AddRefed<TextRangeArray> CreateTextRangeArray(
571 GtkIMContext* aContext, const nsAString& aCompositionString);
574 * SetTextRange() initializes aTextRange with aPangoAttrIter.
576 * @param aPangoAttrIter An iter which represents a clause of the
577 * composition string.
578 * @param aUTF8CompositionString The whole composition string (UTF-8).
579 * @param aUTF16CaretOffset The caret offset in the composition
580 * string encoded as UTF-16.
581 * @param aTextRange The result.
582 * @return true if this initializes aTextRange.
583 * Otherwise, false.
585 bool SetTextRange(PangoAttrIterator* aPangoAttrIter,
586 const gchar* aUTF8CompositionString,
587 uint32_t aUTF16CaretOffset, TextRange& aTextRange) const;
590 * ToNscolor() converts the PangoColor in aPangoAttrColor to nscolor.
592 static nscolor ToNscolor(PangoAttrColor* aPangoAttrColor);
595 * Move the candidate window with "fake" cursor position.
597 * @param aContext A GtkIMContext which is being handled.
599 void SetCursorPosition(GtkIMContext* aContext);
601 // Queries the current selection offset of the window.
602 uint32_t GetSelectionOffset(nsWindow* aWindow);
604 // Get current paragraph text content and cursor position
605 nsresult GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos);
608 * Delete text portion
610 * @param aContext A GtkIMContext which is being handled.
611 * @param aOffset Start offset of the range to delete.
612 * @param aNChars Count of characters to delete. It depends
613 * on |g_utf8_strlen()| what is one character.
615 nsresult DeleteText(GtkIMContext* aContext, int32_t aOffset,
616 uint32_t aNChars);
618 // Called before destroying the context to work around some platform bugs.
619 void PrepareToDestroyContext(GtkIMContext* aContext);
622 * WARNING:
623 * Following methods dispatch gecko events. Then, the focused widget
624 * can be destroyed, and also it can be stolen focus. If they returns
625 * FALSE, callers cannot continue the composition.
626 * - MaybeDispatchKeyEventAsProcessedByIME
627 * - DispatchCompositionStart
628 * - DispatchCompositionChangeEvent
629 * - DispatchCompositionCommitEvent
633 * Dispatch an eKeyDown or eKeyUp event whose mKeyCode value is
634 * NS_VK_PROCESSKEY and mKeyNameIndex is KEY_NAME_INDEX_Process if
635 * we're not in a dead key sequence, mProcessingKeyEvent is nullptr
636 * but mPostingKeyEvents is not empty or mProcessingKeyEvent is not
637 * nullptr and mKeyboardEventWasDispatched is still false. If this
638 * dispatches a keyboard event, this sets mKeyboardEventWasDispatched
639 * to true.
641 * @param aFollowingEvent The following event message.
642 * @return If the caller can continue to handle
643 * composition, returns true. Otherwise,
644 * false. For example, if focus is moved
645 * by dispatched keyboard event, returns
646 * false.
648 bool MaybeDispatchKeyEventAsProcessedByIME(EventMessage aFollowingEvent);
651 * Dispatches a composition start event.
653 * @param aContext A GtkIMContext which is being handled.
654 * @return true if the focused widget is neither
655 * destroyed nor changed. Otherwise, false.
657 bool DispatchCompositionStart(GtkIMContext* aContext);
660 * Dispatches a compositionchange event.
662 * @param aContext A GtkIMContext which is being handled.
663 * @param aCompositionString New composition string.
664 * @return true if the focused widget is neither
665 * destroyed nor changed. Otherwise, false.
667 bool DispatchCompositionChangeEvent(GtkIMContext* aContext,
668 const nsAString& aCompositionString);
671 * Dispatches a compositioncommit event or compositioncommitasis event.
673 * @param aContext A GtkIMContext which is being handled.
674 * @param aCommitString If this is nullptr, the composition will
675 * be committed with last dispatched data.
676 * Otherwise, the composition will be
677 * committed with this value.
678 * @return true if the focused widget is neither
679 * destroyed nor changed. Otherwise, false.
681 bool DispatchCompositionCommitEvent(GtkIMContext* aContext,
682 const nsAString* aCommitString = nullptr);
685 } // namespace widget
686 } // namespace mozilla
688 #endif // #ifndef IMContextWrapper_h_