1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
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_
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"
33 * KeyHandlingState is result of IMContextWrapper::OnKeyEvent().
35 enum class KeyHandlingState
{
36 // The native key event has not been handled by IMContextWrapper.
38 // The native key event was handled by IMContextWrapper.
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
{
50 // TextEventDispatcherListener implementation
53 NS_IMETHOD
NotifyIME(TextEventDispatcher
* aTextEventDispatcher
,
54 const IMENotification
& aNotification
) override
;
55 NS_IMETHOD_(IMENotificationRequests
) GetIMENotificationRequests() override
;
57 OnRemovedFrom(TextEventDispatcher
* aTextEventDispatcher
) override
;
59 WillDispatchKeyboardEvent(TextEventDispatcher
* aTextEventDispatcher
,
60 WidgetKeyboardEvent
& aKeyboardEvent
,
61 uint32_t aIndexOfKeypress
, void* aData
) override
;
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();
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
101 * @param aEvent A native key press or release
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
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
172 static guint16
GetWaitingSynthesizedKeyPressHardwareKeyCode() {
173 return sWaitingSynthesizedKeyPressHardwareKeyCode
;
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
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
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
{
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
262 void RemoveEvent(const GdkEventKey
* aEvent
) {
263 size_t index
= IndexOf(aEvent
);
264 if (NS_WARN_IF(index
== GdkEventKeyQueue::NoIndex())) {
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();
287 * FirstEvent() returns oldest event in the queue.
289 GdkEventKey
* GetFirstEvent() const {
290 if (mEvents
.IsEmpty()) {
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
))) {
319 return GdkEventKeyQueue::NoIndex();
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
;
335 Range() : mOffset(UINT32_MAX
), mLength(UINT32_MAX
) {}
337 bool IsValid() const { return mOffset
!= UINT32_MAX
; }
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";
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
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 {
414 // IME was blurred without a focus change
415 BlurredWithoutFocusChange
,
417 friend std::ostream
& operator<<(std::ostream
& aStream
, IMEFocusState 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";
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
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.
455 // mSetCursorPositionOnKeyEvent true when caret rect or position is updated
456 // with no composition. If true, we update candidate window position
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
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.
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
,
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
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.
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.
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.
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
,
618 // Called before destroying the context to work around some platform bugs.
619 void PrepareToDestroyContext(GtkIMContext
* aContext
);
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
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
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_