1 /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_widget_IMEData_h_
7 #define mozilla_widget_IMEData_h_
12 #include "nsXULAppAPI.h"
24 * Preference for receiving IME updates
26 * If mWantUpdates is not NOTIFY_NOTHING, nsTextStateManager will observe text
27 * change and/or selection change and call nsIWidget::NotifyIME() with
28 * NOTIFY_IME_OF_SELECTION_CHANGE and/or NOTIFY_IME_OF_TEXT_CHANGE.
29 * Please note that the text change observing cost is very expensive especially
30 * on an HTML editor has focus.
31 * If the IME implementation on a particular platform doesn't care about
32 * NOTIFY_IME_OF_SELECTION_CHANGE and/or NOTIFY_IME_OF_TEXT_CHANGE,
33 * they should set mWantUpdates to NOTIFY_NOTHING to avoid the cost.
34 * If the IME implementation needs notifications even while our process is
35 * deactive, it should also set NOTIFY_DURING_DEACTIVE.
37 struct IMENotificationRequests final
{
38 typedef uint8_t Notifications
;
40 enum : Notifications
{
42 NOTIFY_TEXT_CHANGE
= 1 << 1,
43 NOTIFY_POSITION_CHANGE
= 1 << 2,
44 // NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR is used when mouse button is pressed
45 // or released on a character in the focused editor. The notification is
46 // notified to IME as a mouse event. If it's consumed by IME, NotifyIME()
47 // returns NS_SUCCESS_EVENT_CONSUMED. Otherwise, it returns NS_OK if it's
48 // handled without any error.
49 NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR
= 1 << 3,
50 // NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
51 // or more compositions are possible. E.g., Mac and Linux (GTK).
52 NOTIFY_DURING_DEACTIVE
= 1 << 7,
54 NOTIFY_ALL
= NOTIFY_TEXT_CHANGE
| NOTIFY_POSITION_CHANGE
|
55 NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR
,
58 IMENotificationRequests() : mWantUpdates(NOTIFY_NOTHING
) {}
60 explicit IMENotificationRequests(Notifications aWantUpdates
)
61 : mWantUpdates(aWantUpdates
) {}
63 IMENotificationRequests
operator|(
64 const IMENotificationRequests
& aOther
) const {
65 return IMENotificationRequests(aOther
.mWantUpdates
| mWantUpdates
);
67 IMENotificationRequests
& operator|=(const IMENotificationRequests
& aOther
) {
68 mWantUpdates
|= aOther
.mWantUpdates
;
71 bool operator==(const IMENotificationRequests
& aOther
) const {
72 return mWantUpdates
== aOther
.mWantUpdates
;
75 bool WantTextChange() const { return !!(mWantUpdates
& NOTIFY_TEXT_CHANGE
); }
77 bool WantPositionChanged() const {
78 return !!(mWantUpdates
& NOTIFY_POSITION_CHANGE
);
81 bool WantChanges() const { return WantTextChange(); }
83 bool WantMouseButtonEventOnChar() const {
84 return !!(mWantUpdates
& NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR
);
87 bool WantDuringDeactive() const {
88 return !!(mWantUpdates
& NOTIFY_DURING_DEACTIVE
);
91 Notifications mWantUpdates
;
95 * Contains IMEStatus plus information about the current
96 * input context that the IME can use as hints if desired.
99 struct IMEState final
{
101 * IME enabled states, the mEnabled value of
102 * SetInputContext()/GetInputContext() should be one value of following
105 * WARNING: If you change these values, you also need to edit:
106 * nsIDOMWindowUtils.idl
107 * nsContentUtils::GetWidgetStatusFromIMEStatus
111 * 'Disabled' means the user cannot use IME. So, the IME open state should
112 * be 'closed' during 'disabled'.
116 * 'Enabled' means the user can use IME.
120 * 'Password' state is a special case for the password editors.
121 * E.g., on mac, the password editors should disable the non-Roman
122 * keyboard layouts at getting focus. Thus, the password editor may have
123 * special rules on some platforms.
127 * This state is used when a plugin is focused.
128 * When a plug-in is focused content, we should send native events
129 * directly. Because we don't process some native events, but they may
130 * be needed by the plug-in.
134 * 'Unknown' is useful when you cache this enum. So, this shouldn't be
135 * used with nsIWidget::SetInputContext().
142 * IME open states the mOpen value of SetInputContext() should be one value of
143 * OPEN, CLOSE or DONT_CHANGE_OPEN_STATE. GetInputContext() should return
144 * OPEN, CLOSE or OPEN_STATE_NOT_SUPPORTED.
148 * 'Unsupported' means the platform cannot return actual IME open state.
149 * This value is used only by GetInputContext().
151 OPEN_STATE_NOT_SUPPORTED
,
153 * 'Don't change' means the widget shouldn't change IME open state when
154 * SetInputContext() is called.
156 DONT_CHANGE_OPEN_STATE
= OPEN_STATE_NOT_SUPPORTED
,
158 * 'Open' means that IME should compose in its primary language (or latest
159 * input mode except direct ASCII character input mode). Even if IME is
160 * opened by this value, users should be able to close IME by theirselves.
161 * Web contents can specify this value by |ime-mode: active;|.
165 * 'Closed' means that IME shouldn't handle key events (or should handle
166 * as ASCII character inputs on mobile device). Even if IME is closed by
167 * this value, users should be able to open IME by theirselves.
168 * Web contents can specify this value by |ime-mode: inactive;|.
174 IMEState() : mEnabled(ENABLED
), mOpen(DONT_CHANGE_OPEN_STATE
) {}
176 explicit IMEState(Enabled aEnabled
, Open aOpen
= DONT_CHANGE_OPEN_STATE
)
177 : mEnabled(aEnabled
), mOpen(aOpen
) {}
179 // Returns true if the user can input characters.
180 // This means that a plain text editor, an HTML editor, a password editor or
181 // a plain text editor whose ime-mode is "disabled".
182 bool IsEditable() const {
183 return mEnabled
== ENABLED
|| mEnabled
== PASSWORD
;
185 // Returns true if the user might be able to input characters.
186 // This means that a plain text editor, an HTML editor, a password editor,
187 // a plain text editor whose ime-mode is "disabled" or a windowless plugin
189 bool MaybeEditable() const { return IsEditable() || mEnabled
== PLUGIN
; }
192 // NS_ONLY_ONE_NATIVE_IME_CONTEXT is a special value of native IME context.
193 // If there can be only one IME composition in a process, this can be used.
194 #define NS_ONLY_ONE_NATIVE_IME_CONTEXT \
195 (reinterpret_cast<void*>(static_cast<intptr_t>(-1)))
197 struct NativeIMEContext final
{
198 // Pointer to native IME context. Typically this is the result of
199 // nsIWidget::GetNativeData(NS_RAW_NATIVE_IME_CONTEXT) in the parent process.
200 // See also NS_ONLY_ONE_NATIVE_IME_CONTEXT.
201 uintptr_t mRawNativeIMEContext
;
202 // Process ID of the origin of mNativeIMEContext.
203 uint64_t mOriginProcessID
;
205 NativeIMEContext() : mRawNativeIMEContext(0), mOriginProcessID(0) {
209 explicit NativeIMEContext(nsIWidget
* aWidget
)
210 : mRawNativeIMEContext(0), mOriginProcessID(0) {
214 bool IsValid() const {
215 return mRawNativeIMEContext
&&
216 mOriginProcessID
!= static_cast<uintptr_t>(-1);
219 void Init(nsIWidget
* aWidget
);
220 void InitWithRawNativeIMEContext(const void* aRawNativeIMEContext
) {
221 InitWithRawNativeIMEContext(const_cast<void*>(aRawNativeIMEContext
));
223 void InitWithRawNativeIMEContext(void* aRawNativeIMEContext
);
225 bool operator==(const NativeIMEContext
& aOther
) const {
226 return mRawNativeIMEContext
== aOther
.mRawNativeIMEContext
&&
227 mOriginProcessID
== aOther
.mOriginProcessID
;
229 bool operator!=(const NativeIMEContext
& aOther
) const {
230 return !(*this == aOther
);
234 struct InputContext final
{
236 : mOrigin(XRE_IsParentProcess() ? ORIGIN_MAIN
: ORIGIN_CONTENT
),
237 mMayBeIMEUnaware(false),
238 mHasHandledUserInput(false),
239 mInPrivateBrowsing(false) {}
241 // If InputContext instance is a static variable, any heap allocated stuff
242 // of its members need to be deleted at XPCOM shutdown. Otherwise, it's
243 // detected as memory leak.
245 mHTMLInputType
.Truncate();
246 mHTMLInputInputmode
.Truncate();
247 mActionHint
.Truncate();
250 bool IsPasswordEditor() const {
251 return mHTMLInputType
.LowerCaseEqualsLiteral("password");
256 /* The type of the input if the input is a html input field */
257 nsString mHTMLInputType
;
259 /* The type of the inputmode */
260 nsString mHTMLInputInputmode
;
262 /* A hint for the action that is performed when the input is submitted */
263 nsString mActionHint
;
266 * mOrigin indicates whether this focus event refers to main or remote
270 // Adjusting focus of content on the main process
272 // Adjusting focus of content in a remote process
277 /* True if the webapp may be unaware of IME events such as input event or
278 * composiion events. This enables a key-events-only mode on Android for
279 * compatibility with webapps relying on key listeners. */
280 bool mMayBeIMEUnaware
;
283 * True if the document has ever received user input
285 bool mHasHandledUserInput
;
287 /* Whether the owning document of the input element has been loaded
288 * in private browsing mode. */
289 bool mInPrivateBrowsing
;
291 bool IsOriginMainProcess() const { return mOrigin
== ORIGIN_MAIN
; }
293 bool IsOriginContentProcess() const { return mOrigin
== ORIGIN_CONTENT
; }
295 bool IsOriginCurrentProcess() const {
296 if (XRE_IsParentProcess()) {
297 return IsOriginMainProcess();
299 return IsOriginContentProcess();
303 // FYI: Implemented in nsBaseWidget.cpp
304 const char* ToChar(InputContext::Origin aOrigin
);
306 struct InputContextAction final
{
308 * mCause indicates what action causes calling nsIWidget::SetInputContext().
309 * It must be one of following values.
312 // The cause is unknown but originated from content. Focus might have been
313 // changed by content script.
315 // The cause is unknown but originated from chrome. Focus might have been
316 // changed by chrome script.
317 CAUSE_UNKNOWN_CHROME
,
318 // The cause is user's keyboard operation.
320 // The cause is user's mouse operation.
322 // The cause is user's touch operation (implies mouse)
324 // The cause is unknown but it occurs during user input except keyboard
325 // input. E.g., an event handler of a user input event moves focus.
326 CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT
,
327 // The cause is unknown but it occurs during keyboard input.
328 CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT
,
333 * mFocusChange indicates what happened for focus.
337 // A content got focus.
339 // Focused content lost focus.
341 // Menu got pseudo focus that means focused content isn't changed but
342 // keyboard events will be handled by menu.
343 MENU_GOT_PSEUDO_FOCUS
,
344 // Menu lost pseudo focus that means focused content will handle keyboard
346 MENU_LOST_PSEUDO_FOCUS
,
347 // The widget is created. When a widget is crated, it may need to notify
348 // IME module to initialize its native IME context. In such case, this is
349 // used. I.e., this isn't used by IMEStateManager.
352 FocusChange mFocusChange
;
354 bool ContentGotFocusByTrustedCause() const {
355 return (mFocusChange
== GOT_FOCUS
&& mCause
!= CAUSE_UNKNOWN
);
358 bool UserMightRequestOpenVKB() const {
359 // If focus is changed, user must not request to open VKB.
360 if (mFocusChange
!= FOCUS_NOT_CHANGED
) {
364 // If user clicks or touches focused editor, user must request to open
368 // If script does something during a user input and that causes changing
369 // input context, user might request to open VKB. E.g., user clicks
370 // dummy editor and JS moves focus to an actual editable node. However,
371 // this should return false if the user input is a keyboard event since
372 // physical keyboard operation shouldn't cause opening VKB.
373 case CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT
:
381 * IsHandlingUserInput() returns true if it's caused by a user action directly
382 * or it's caused by script or something but it occurred while we're handling
383 * a user action. E.g., when it's caused by Element.focus() in an event
384 * handler of a user input, this returns true.
386 static bool IsHandlingUserInput(Cause aCause
) {
391 case CAUSE_UNKNOWN_DURING_NON_KEYBOARD_INPUT
:
392 case CAUSE_UNKNOWN_DURING_KEYBOARD_INPUT
:
399 bool IsHandlingUserInput() const { return IsHandlingUserInput(mCause
); }
402 : mCause(CAUSE_UNKNOWN
), mFocusChange(FOCUS_NOT_CHANGED
) {}
404 explicit InputContextAction(Cause aCause
,
405 FocusChange aFocusChange
= FOCUS_NOT_CHANGED
)
406 : mCause(aCause
), mFocusChange(aFocusChange
) {}
409 // IMEMessage is shared by IMEStateManager and TextComposition.
410 // Update values in GeckoEditable.java if you make changes here.
411 // XXX Negative values are used in Android...
412 typedef int8_t IMEMessageType
;
413 enum IMEMessage
: IMEMessageType
{
414 // This is used by IMENotification internally. This means that the instance
415 // hasn't been initialized yet.
416 NOTIFY_IME_OF_NOTHING
,
417 // An editable content is getting focus
419 // An editable content is losing focus
421 // Selection in the focused editable content is changed
422 NOTIFY_IME_OF_SELECTION_CHANGE
,
423 // Text in the focused editable content is changed
424 NOTIFY_IME_OF_TEXT_CHANGE
,
425 // Notified when a dispatched composition event is handled by the
426 // contents. This must be notified after the other notifications.
427 // Note that if a remote process has focus, this is notified only once when
428 // all dispatched events are handled completely. So, the receiver shouldn't
429 // count number of received this notification for comparing with the number
430 // of dispatched events.
431 // NOTE: If a composition event causes moving focus from the focused editor,
432 // this notification may not be notified as usual. Even in such case,
433 // NOTIFY_IME_OF_BLUR is always sent. So, notification listeners
434 // should tread the blur notification as including this if there is
435 // pending composition events.
436 NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED
,
437 // Position or size of focused element may be changed.
438 NOTIFY_IME_OF_POSITION_CHANGE
,
439 // Mouse button event is fired on a character in focused editor
440 NOTIFY_IME_OF_MOUSE_BUTTON_EVENT
,
441 // Request to commit current composition to IME
442 // (some platforms may not support)
443 REQUEST_TO_COMMIT_COMPOSITION
,
444 // Request to cancel current composition to IME
445 // (some platforms may not support)
446 REQUEST_TO_CANCEL_COMPOSITION
449 // FYI: Implemented in nsBaseWidget.cpp
450 const char* ToChar(IMEMessage aIMEMessage
);
452 struct IMENotification final
{
453 IMENotification() : mMessage(NOTIFY_IME_OF_NOTHING
), mSelectionChangeData() {}
455 IMENotification(const IMENotification
& aOther
)
456 : mMessage(NOTIFY_IME_OF_NOTHING
) {
460 ~IMENotification() { Clear(); }
462 MOZ_IMPLICIT
IMENotification(IMEMessage aMessage
)
463 : mMessage(aMessage
), mSelectionChangeData() {
465 case NOTIFY_IME_OF_SELECTION_CHANGE
:
466 mSelectionChangeData
.mString
= new nsString();
467 mSelectionChangeData
.Clear();
469 case NOTIFY_IME_OF_TEXT_CHANGE
:
470 mTextChangeData
.Clear();
472 case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT
:
473 mMouseButtonEventData
.mEventMessage
= eVoidEvent
;
474 mMouseButtonEventData
.mOffset
= UINT32_MAX
;
475 mMouseButtonEventData
.mCursorPos
.Set(nsIntPoint(0, 0));
476 mMouseButtonEventData
.mCharRect
.Set(nsIntRect(0, 0, 0, 0));
477 mMouseButtonEventData
.mButton
= -1;
478 mMouseButtonEventData
.mButtons
= 0;
479 mMouseButtonEventData
.mModifiers
= 0;
486 void Assign(const IMENotification
& aOther
) {
487 bool changingMessage
= mMessage
!= aOther
.mMessage
;
488 if (changingMessage
) {
490 mMessage
= aOther
.mMessage
;
493 case NOTIFY_IME_OF_SELECTION_CHANGE
:
494 if (changingMessage
) {
495 mSelectionChangeData
.mString
= new nsString();
497 mSelectionChangeData
.Assign(aOther
.mSelectionChangeData
);
499 case NOTIFY_IME_OF_TEXT_CHANGE
:
500 mTextChangeData
= aOther
.mTextChangeData
;
502 case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT
:
503 mMouseButtonEventData
= aOther
.mMouseButtonEventData
;
510 IMENotification
& operator=(const IMENotification
& aOther
) {
516 if (mMessage
== NOTIFY_IME_OF_SELECTION_CHANGE
) {
517 MOZ_ASSERT(mSelectionChangeData
.mString
);
518 delete mSelectionChangeData
.mString
;
519 mSelectionChangeData
.mString
= nullptr;
521 mMessage
= NOTIFY_IME_OF_NOTHING
;
524 bool HasNotification() const { return mMessage
!= NOTIFY_IME_OF_NOTHING
; }
526 void MergeWith(const IMENotification
& aNotification
) {
528 case NOTIFY_IME_OF_NOTHING
:
529 MOZ_ASSERT(aNotification
.mMessage
!= NOTIFY_IME_OF_NOTHING
);
530 Assign(aNotification
);
532 case NOTIFY_IME_OF_SELECTION_CHANGE
:
533 MOZ_ASSERT(aNotification
.mMessage
== NOTIFY_IME_OF_SELECTION_CHANGE
);
534 mSelectionChangeData
.Assign(aNotification
.mSelectionChangeData
);
536 case NOTIFY_IME_OF_TEXT_CHANGE
:
537 MOZ_ASSERT(aNotification
.mMessage
== NOTIFY_IME_OF_TEXT_CHANGE
);
538 mTextChangeData
+= aNotification
.mTextChangeData
;
540 case NOTIFY_IME_OF_POSITION_CHANGE
:
541 case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED
:
542 MOZ_ASSERT(aNotification
.mMessage
== mMessage
);
545 MOZ_CRASH("Merging notification isn't supported");
556 void Set(const nsIntPoint
& aPoint
) {
560 nsIntPoint
AsIntPoint() const { return nsIntPoint(mX
, mY
); }
569 void Set(const nsIntRect
& aRect
) {
570 aRect
.GetRect(&mX
, &mY
, &mWidth
, &mHeight
);
572 nsIntRect
AsIntRect() const { return nsIntRect(mX
, mY
, mWidth
, mHeight
); }
575 // NOTIFY_IME_OF_SELECTION_CHANGE specific data
576 struct SelectionChangeDataBase
{
583 // Writing mode at the selection.
584 uint8_t mWritingMode
;
587 bool mCausedByComposition
;
588 bool mCausedBySelectionEvent
;
589 bool mOccurredDuringComposition
;
591 void SetWritingMode(const WritingMode
& aWritingMode
);
592 WritingMode
GetWritingMode() const;
594 uint32_t StartOffset() const {
595 return mOffset
+ (mReversed
? Length() : 0);
597 uint32_t EndOffset() const { return mOffset
+ (mReversed
? 0 : Length()); }
598 const nsString
& String() const { return *mString
; }
599 uint32_t Length() const { return mString
->Length(); }
600 bool IsInInt32Range() const { return mOffset
+ Length() <= INT32_MAX
; }
601 bool IsCollapsed() const { return mString
->IsEmpty(); }
602 void ClearSelectionData() {
603 mOffset
= UINT32_MAX
;
609 ClearSelectionData();
610 mCausedByComposition
= false;
611 mCausedBySelectionEvent
= false;
612 mOccurredDuringComposition
= false;
614 bool IsValid() const { return mOffset
!= UINT32_MAX
; }
615 void Assign(const SelectionChangeDataBase
& aOther
) {
616 mOffset
= aOther
.mOffset
;
617 *mString
= aOther
.String();
618 mWritingMode
= aOther
.mWritingMode
;
619 mReversed
= aOther
.mReversed
;
620 AssignReason(aOther
.mCausedByComposition
, aOther
.mCausedBySelectionEvent
,
621 aOther
.mOccurredDuringComposition
);
623 void AssignReason(bool aCausedByComposition
, bool aCausedBySelectionEvent
,
624 bool aOccurredDuringComposition
) {
625 mCausedByComposition
= aCausedByComposition
;
626 mCausedBySelectionEvent
= aCausedBySelectionEvent
;
627 mOccurredDuringComposition
= aOccurredDuringComposition
;
631 // SelectionChangeDataBase cannot have constructors because it's used in
632 // the union. Therefore, SelectionChangeData should only implement
633 // constructors. In other words, add other members to
634 // SelectionChangeDataBase.
635 struct SelectionChangeData final
: public SelectionChangeDataBase
{
636 SelectionChangeData() {
637 mString
= &mStringInstance
;
640 explicit SelectionChangeData(const SelectionChangeDataBase
& aOther
) {
641 mString
= &mStringInstance
;
644 SelectionChangeData(const SelectionChangeData
& aOther
) {
645 mString
= &mStringInstance
;
648 SelectionChangeData
& operator=(const SelectionChangeDataBase
& aOther
) {
649 mString
= &mStringInstance
;
653 SelectionChangeData
& operator=(const SelectionChangeData
& aOther
) {
654 mString
= &mStringInstance
;
660 // When SelectionChangeData is used outside of union, it shouldn't create
661 // nsString instance in the heap as far as possible.
662 nsString mStringInstance
;
665 struct TextChangeDataBase
{
666 // mStartOffset is the start offset of modified or removed text in
667 // original content and inserted text in new content.
668 uint32_t mStartOffset
;
669 // mRemovalEndOffset is the end offset of modified or removed text in
670 // original content. If the value is same as mStartOffset, no text hasn't
672 uint32_t mRemovedEndOffset
;
673 // mAddedEndOffset is the end offset of inserted text or same as
674 // mStartOffset if just removed. The vlaue is offset in the new content.
675 uint32_t mAddedEndOffset
;
677 // Note that TextChangeDataBase may be the result of merging two or more
678 // changes especially in e10s mode.
680 // mCausedOnlyByComposition is true only when *all* merged changes are
681 // caused by composition.
682 bool mCausedOnlyByComposition
;
683 // mIncludingChangesDuringComposition is true if at least one change which
684 // is not caused by composition occurred during the last composition.
685 // Note that if after the last composition is finished and there are some
686 // changes not caused by composition, this is set to false.
687 bool mIncludingChangesDuringComposition
;
688 // mIncludingChangesWithoutComposition is true if there is at least one
689 // change which did occur when there wasn't a composition ongoing.
690 bool mIncludingChangesWithoutComposition
;
692 uint32_t OldLength() const {
693 MOZ_ASSERT(IsValid());
694 return mRemovedEndOffset
- mStartOffset
;
696 uint32_t NewLength() const {
697 MOZ_ASSERT(IsValid());
698 return mAddedEndOffset
- mStartOffset
;
701 // Positive if text is added. Negative if text is removed.
702 int64_t Difference() const { return mAddedEndOffset
- mRemovedEndOffset
; }
704 bool IsInInt32Range() const {
705 MOZ_ASSERT(IsValid());
706 return mStartOffset
<= INT32_MAX
&& mRemovedEndOffset
<= INT32_MAX
&&
707 mAddedEndOffset
<= INT32_MAX
;
710 bool IsValid() const {
711 return !(mStartOffset
== UINT32_MAX
&& !mRemovedEndOffset
&&
716 mStartOffset
= UINT32_MAX
;
717 mRemovedEndOffset
= mAddedEndOffset
= 0;
720 void MergeWith(const TextChangeDataBase
& aOther
);
721 TextChangeDataBase
& operator+=(const TextChangeDataBase
& aOther
) {
728 #endif // #ifdef DEBUG
731 // TextChangeDataBase cannot have constructors because they are used in union.
732 // Therefore, TextChangeData should only implement constructor. In other
733 // words, add other members to TextChangeDataBase.
734 struct TextChangeData
: public TextChangeDataBase
{
735 TextChangeData() { Clear(); }
737 TextChangeData(uint32_t aStartOffset
, uint32_t aRemovedEndOffset
,
738 uint32_t aAddedEndOffset
, bool aCausedByComposition
,
739 bool aOccurredDuringComposition
) {
740 MOZ_ASSERT(aRemovedEndOffset
>= aStartOffset
,
741 "removed end offset must not be smaller than start offset");
742 MOZ_ASSERT(aAddedEndOffset
>= aStartOffset
,
743 "added end offset must not be smaller than start offset");
744 mStartOffset
= aStartOffset
;
745 mRemovedEndOffset
= aRemovedEndOffset
;
746 mAddedEndOffset
= aAddedEndOffset
;
747 mCausedOnlyByComposition
= aCausedByComposition
;
748 mIncludingChangesDuringComposition
=
749 !aCausedByComposition
&& aOccurredDuringComposition
;
750 mIncludingChangesWithoutComposition
=
751 !aCausedByComposition
&& !aOccurredDuringComposition
;
755 struct MouseButtonEventData
{
756 // The value of WidgetEvent::mMessage
757 EventMessage mEventMessage
;
758 // Character offset from the start of the focused editor under the cursor
760 // Cursor position in pixels relative to the widget
762 // Character rect in pixels under the cursor relative to the widget
764 // The value of WidgetMouseEventBase::button and buttons
767 // The value of WidgetInputEvent::modifiers
768 Modifiers mModifiers
;
772 // NOTIFY_IME_OF_SELECTION_CHANGE specific data
773 SelectionChangeDataBase mSelectionChangeData
;
775 // NOTIFY_IME_OF_TEXT_CHANGE specific data
776 TextChangeDataBase mTextChangeData
;
778 // NOTIFY_IME_OF_MOUSE_BUTTON_EVENT specific data
779 MouseButtonEventData mMouseButtonEventData
;
782 void SetData(const SelectionChangeDataBase
& aSelectionChangeData
) {
783 MOZ_RELEASE_ASSERT(mMessage
== NOTIFY_IME_OF_SELECTION_CHANGE
);
784 mSelectionChangeData
.Assign(aSelectionChangeData
);
787 void SetData(const TextChangeDataBase
& aTextChangeData
) {
788 MOZ_RELEASE_ASSERT(mMessage
== NOTIFY_IME_OF_TEXT_CHANGE
);
789 mTextChangeData
= aTextChangeData
;
793 struct CandidateWindowPosition
{
794 // Upper left corner of the candidate window if mExcludeRect is false.
795 // Otherwise, the position currently interested. E.g., caret position.
796 LayoutDeviceIntPoint mPoint
;
797 // Rect which shouldn't be overlapped with the candidate window.
798 // This is valid only when mExcludeRect is true.
799 LayoutDeviceIntRect mRect
;
800 // See explanation of mPoint and mRect.
804 } // namespace widget
805 } // namespace mozilla
807 #endif // #ifndef mozilla_widget_IMEData_h_