LCOV - code coverage report
Current view: top level - widget - IMEData.h (source / functions) Hit Total Coverage
Test: output.info Lines: 29 221 13.1 %
Date: 2017-07-14 16:53:18 Functions: 12 57 21.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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/. */
       5             : 
       6             : #ifndef mozilla_widget_IMEData_h_
       7             : #define mozilla_widget_IMEData_h_
       8             : 
       9             : #include "nsPoint.h"
      10             : #include "nsRect.h"
      11             : #include "nsStringGlue.h"
      12             : #include "nsXULAppAPI.h"
      13             : #include "Units.h"
      14             : 
      15             : class nsIWidget;
      16             : 
      17             : namespace mozilla {
      18             : 
      19             : class WritingMode;
      20             : 
      21             : namespace widget {
      22             : 
      23             : /**
      24             :  * Preference for receiving IME updates
      25             :  *
      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.
      36             :  */
      37             : struct IMENotificationRequests final
      38             : {
      39             :   typedef uint8_t Notifications;
      40             : 
      41             :   enum : Notifications
      42             :   {
      43             :     NOTIFY_NOTHING                       = 0,
      44             :     NOTIFY_TEXT_CHANGE                   = 1 << 1,
      45             :     NOTIFY_POSITION_CHANGE               = 1 << 2,
      46             :     // NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR is used when mouse button is pressed
      47             :     // or released on a character in the focused editor.  The notification is
      48             :     // notified to IME as a mouse event.  If it's consumed by IME, NotifyIME()
      49             :     // returns NS_SUCCESS_EVENT_CONSUMED.  Otherwise, it returns NS_OK if it's
      50             :     // handled without any error.
      51             :     NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR    = 1 << 3,
      52             :     // NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
      53             :     //       or more compositions are possible.  E.g., Mac and Linux (GTK).
      54             :     NOTIFY_DURING_DEACTIVE               = 1 << 7
      55             :   };
      56             : 
      57           2 :   IMENotificationRequests()
      58           2 :     : mWantUpdates(NOTIFY_NOTHING)
      59             :   {
      60           2 :   }
      61             : 
      62           0 :   explicit IMENotificationRequests(Notifications aWantUpdates)
      63           0 :     : mWantUpdates(aWantUpdates)
      64             :   {
      65           0 :   }
      66             : 
      67             :   IMENotificationRequests operator|(const IMENotificationRequests& aOther) const
      68             :   {
      69             :     return IMENotificationRequests(aOther.mWantUpdates | mWantUpdates);
      70             :   }
      71           0 :   IMENotificationRequests& operator|=(const IMENotificationRequests& aOther)
      72             :   {
      73           0 :     mWantUpdates |= aOther.mWantUpdates;
      74           0 :     return *this;
      75             :   }
      76             :   bool operator==(const IMENotificationRequests& aOther) const
      77             :   {
      78             :     return mWantUpdates == aOther.mWantUpdates;
      79             :   }
      80             : 
      81           0 :   bool WantTextChange() const
      82             :   {
      83           0 :     return !!(mWantUpdates & NOTIFY_TEXT_CHANGE);
      84             :   }
      85             : 
      86           0 :   bool WantPositionChanged() const
      87             :   {
      88           0 :     return !!(mWantUpdates & NOTIFY_POSITION_CHANGE);
      89             :   }
      90             : 
      91             :   bool WantChanges() const
      92             :   {
      93             :     return WantTextChange();
      94             :   }
      95             : 
      96           0 :   bool WantMouseButtonEventOnChar() const
      97             :   {
      98           0 :     return !!(mWantUpdates & NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR);
      99             :   }
     100             : 
     101           0 :   bool WantDuringDeactive() const
     102             :   {
     103           0 :     return !!(mWantUpdates & NOTIFY_DURING_DEACTIVE);
     104             :   }
     105             : 
     106             :   Notifications mWantUpdates;
     107             : };
     108             : 
     109             : /**
     110             :  * Contains IMEStatus plus information about the current 
     111             :  * input context that the IME can use as hints if desired.
     112             :  */
     113             : 
     114             : struct IMEState final
     115             : {
     116             :   /**
     117             :    * IME enabled states, the mEnabled value of
     118             :    * SetInputContext()/GetInputContext() should be one value of following
     119             :    * values.
     120             :    *
     121             :    * WARNING: If you change these values, you also need to edit:
     122             :    *   nsIDOMWindowUtils.idl
     123             :    *   nsContentUtils::GetWidgetStatusFromIMEStatus
     124             :    */
     125             :   enum Enabled
     126             :   {
     127             :     /**
     128             :      * 'Disabled' means the user cannot use IME. So, the IME open state should
     129             :      * be 'closed' during 'disabled'.
     130             :      */
     131             :     DISABLED,
     132             :     /**
     133             :      * 'Enabled' means the user can use IME.
     134             :      */
     135             :     ENABLED,
     136             :     /**
     137             :      * 'Password' state is a special case for the password editors.
     138             :      * E.g., on mac, the password editors should disable the non-Roman
     139             :      * keyboard layouts at getting focus. Thus, the password editor may have
     140             :      * special rules on some platforms.
     141             :      */
     142             :     PASSWORD,
     143             :     /**
     144             :      * This state is used when a plugin is focused.
     145             :      * When a plug-in is focused content, we should send native events
     146             :      * directly. Because we don't process some native events, but they may
     147             :      * be needed by the plug-in.
     148             :      */
     149             :     PLUGIN,
     150             :     /**
     151             :      * 'Unknown' is useful when you cache this enum.  So, this shouldn't be
     152             :      * used with nsIWidget::SetInputContext().
     153             :      */
     154             :     UNKNOWN
     155             :   };
     156             :   Enabled mEnabled;
     157             : 
     158             :   /**
     159             :    * IME open states the mOpen value of SetInputContext() should be one value of
     160             :    * OPEN, CLOSE or DONT_CHANGE_OPEN_STATE.  GetInputContext() should return
     161             :    * OPEN, CLOSE or OPEN_STATE_NOT_SUPPORTED.
     162             :    */
     163             :   enum Open
     164             :   {
     165             :     /**
     166             :      * 'Unsupported' means the platform cannot return actual IME open state.
     167             :      * This value is used only by GetInputContext().
     168             :      */
     169             :     OPEN_STATE_NOT_SUPPORTED,
     170             :     /**
     171             :      * 'Don't change' means the widget shouldn't change IME open state when
     172             :      * SetInputContext() is called.
     173             :      */
     174             :     DONT_CHANGE_OPEN_STATE = OPEN_STATE_NOT_SUPPORTED,
     175             :     /**
     176             :      * 'Open' means that IME should compose in its primary language (or latest
     177             :      * input mode except direct ASCII character input mode).  Even if IME is
     178             :      * opened by this value, users should be able to close IME by theirselves.
     179             :      * Web contents can specify this value by |ime-mode: active;|.
     180             :      */
     181             :     OPEN,
     182             :     /**
     183             :      * 'Closed' means that IME shouldn't handle key events (or should handle
     184             :      * as ASCII character inputs on mobile device).  Even if IME is closed by
     185             :      * this value, users should be able to open IME by theirselves.
     186             :      * Web contents can specify this value by |ime-mode: inactive;|.
     187             :      */
     188             :     CLOSED
     189             :   };
     190             :   Open mOpen;
     191             : 
     192          11 :   IMEState()
     193          11 :     : mEnabled(ENABLED)
     194          11 :     , mOpen(DONT_CHANGE_OPEN_STATE)
     195             :   {
     196          11 :   }
     197             : 
     198           5 :   explicit IMEState(Enabled aEnabled, Open aOpen = DONT_CHANGE_OPEN_STATE)
     199           5 :     : mEnabled(aEnabled)
     200           5 :     , mOpen(aOpen)
     201             :   {
     202           5 :   }
     203             : 
     204             :   // Returns true if the user can input characters.
     205             :   // This means that a plain text editor, an HTML editor, a password editor or
     206             :   // a plain text editor whose ime-mode is "disabled".
     207           4 :   bool IsEditable() const
     208             :   {
     209           4 :     return mEnabled == ENABLED || mEnabled == PASSWORD;
     210             :   }
     211             :   // Returns true if the user might be able to input characters.
     212             :   // This means that a plain text editor, an HTML editor, a password editor,
     213             :   // a plain text editor whose ime-mode is "disabled" or a windowless plugin
     214             :   // has focus.
     215           0 :   bool MaybeEditable() const
     216             :   {
     217           0 :     return IsEditable() || mEnabled == PLUGIN;
     218             :   }
     219             : };
     220             : 
     221             : // NS_ONLY_ONE_NATIVE_IME_CONTEXT is a special value of native IME context.
     222             : // If there can be only one IME composition in a process, this can be used.
     223             : #define NS_ONLY_ONE_NATIVE_IME_CONTEXT \
     224             :   (reinterpret_cast<void*>(static_cast<intptr_t>(-1)))
     225             : 
     226             : struct NativeIMEContext final
     227             : {
     228             :   // Pointer to native IME context.  Typically this is the result of
     229             :   // nsIWidget::GetNativeData(NS_RAW_NATIVE_IME_CONTEXT) in the parent process.
     230             :   // See also NS_ONLY_ONE_NATIVE_IME_CONTEXT.
     231             :   uintptr_t mRawNativeIMEContext;
     232             :   // Process ID of the origin of mNativeIMEContext.
     233             :   uint64_t mOriginProcessID;
     234             : 
     235           1 :   NativeIMEContext()
     236           1 :   {
     237           1 :     Init(nullptr);
     238           1 :   }
     239             : 
     240           0 :   explicit NativeIMEContext(nsIWidget* aWidget)
     241           0 :   {
     242           0 :     Init(aWidget);
     243           0 :   }
     244             : 
     245           0 :   bool IsValid() const
     246             :   {
     247           0 :     return mRawNativeIMEContext &&
     248           0 :            mOriginProcessID != static_cast<uintptr_t>(-1);
     249             :   }
     250             : 
     251             :   void Init(nsIWidget* aWidget);
     252             :   void InitWithRawNativeIMEContext(const void* aRawNativeIMEContext)
     253             :   {
     254             :     InitWithRawNativeIMEContext(const_cast<void*>(aRawNativeIMEContext));
     255             :   }
     256             :   void InitWithRawNativeIMEContext(void* aRawNativeIMEContext);
     257             : 
     258           0 :   bool operator==(const NativeIMEContext& aOther) const
     259             :   {
     260           0 :     return mRawNativeIMEContext == aOther.mRawNativeIMEContext &&
     261           0 :            mOriginProcessID == aOther.mOriginProcessID;
     262             :   }
     263           0 :   bool operator!=(const NativeIMEContext& aOther) const
     264             :   {
     265           0 :     return !(*this == aOther);
     266             :   }
     267             : };
     268             : 
     269          16 : struct InputContext final
     270             : {
     271          11 :   InputContext()
     272          22 :     : mOrigin(XRE_IsParentProcess() ? ORIGIN_MAIN : ORIGIN_CONTENT)
     273          22 :     , mMayBeIMEUnaware(false)
     274             :   {
     275          11 :   }
     276             : 
     277             :   bool IsPasswordEditor() const
     278             :   {
     279             :     return mHTMLInputType.LowerCaseEqualsLiteral("password");
     280             :   }
     281             : 
     282             :   IMEState mIMEState;
     283             : 
     284             :   /* The type of the input if the input is a html input field */
     285             :   nsString mHTMLInputType;
     286             : 
     287             :   /* The type of the inputmode */
     288             :   nsString mHTMLInputInputmode;
     289             : 
     290             :   /* A hint for the action that is performed when the input is submitted */
     291             :   nsString mActionHint;
     292             : 
     293             :   /**
     294             :    * mOrigin indicates whether this focus event refers to main or remote
     295             :    * content.
     296             :    */
     297             :   enum Origin
     298             :   {
     299             :     // Adjusting focus of content on the main process
     300             :     ORIGIN_MAIN,
     301             :     // Adjusting focus of content in a remote process
     302             :     ORIGIN_CONTENT
     303             :   };
     304             :   Origin mOrigin;
     305             : 
     306             :   /* True if the webapp may be unaware of IME events such as input event or
     307             :    * composiion events. This enables a key-events-only mode on Android for
     308             :    * compatibility with webapps relying on key listeners. */
     309             :   bool mMayBeIMEUnaware;
     310             : 
     311             :   bool IsOriginMainProcess() const
     312             :   {
     313             :     return mOrigin == ORIGIN_MAIN;
     314             :   }
     315             : 
     316             :   bool IsOriginContentProcess() const
     317             :   {
     318             :     return mOrigin == ORIGIN_CONTENT;
     319             :   }
     320             : 
     321             :   bool IsOriginCurrentProcess() const
     322             :   {
     323             :     if (XRE_IsParentProcess()) {
     324             :       return IsOriginMainProcess();
     325             :     }
     326             :     return IsOriginContentProcess();
     327             :   }
     328             : };
     329             : 
     330             : // FYI: Implemented in nsBaseWidget.cpp
     331             : const char* ToChar(InputContext::Origin aOrigin);
     332             : 
     333             : struct InputContextAction final
     334             : {
     335             :   /**
     336             :    * mCause indicates what action causes calling nsIWidget::SetInputContext().
     337             :    * It must be one of following values.
     338             :    */
     339             :   enum Cause
     340             :   {
     341             :     // The cause is unknown but originated from content. Focus might have been
     342             :     // changed by content script.
     343             :     CAUSE_UNKNOWN,
     344             :     // The cause is unknown but originated from chrome. Focus might have been
     345             :     // changed by chrome script.
     346             :     CAUSE_UNKNOWN_CHROME,
     347             :     // The cause is user's keyboard operation.
     348             :     CAUSE_KEY,
     349             :     // The cause is user's mouse operation.
     350             :     CAUSE_MOUSE,
     351             :     // The cause is user's touch operation (implies mouse)
     352             :     CAUSE_TOUCH
     353             :   };
     354             :   Cause mCause;
     355             : 
     356             :   /**
     357             :    * mFocusChange indicates what happened for focus.
     358             :    */
     359             :   enum FocusChange
     360             :   {
     361             :     FOCUS_NOT_CHANGED,
     362             :     // A content got focus.
     363             :     GOT_FOCUS,
     364             :     // Focused content lost focus.
     365             :     LOST_FOCUS,
     366             :     // Menu got pseudo focus that means focused content isn't changed but
     367             :     // keyboard events will be handled by menu.
     368             :     MENU_GOT_PSEUDO_FOCUS,
     369             :     // Menu lost pseudo focus that means focused content will handle keyboard
     370             :     // events.
     371             :     MENU_LOST_PSEUDO_FOCUS,
     372             :     // The widget is created.  When a widget is crated, it may need to notify
     373             :     // IME module to initialize its native IME context.  In such case, this is
     374             :     // used.  I.e., this isn't used by IMEStateManager.
     375             :     WIDGET_CREATED
     376             :   };
     377             :   FocusChange mFocusChange;
     378             : 
     379             :   bool ContentGotFocusByTrustedCause() const
     380             :   {
     381             :     return (mFocusChange == GOT_FOCUS &&
     382             :             mCause != CAUSE_UNKNOWN);
     383             :   }
     384             : 
     385             :   bool UserMightRequestOpenVKB() const
     386             :   {
     387             :     return (mFocusChange == FOCUS_NOT_CHANGED &&
     388             :             (mCause == CAUSE_MOUSE || mCause == CAUSE_TOUCH));
     389             :   }
     390             : 
     391             :   static bool IsUserAction(Cause aCause)
     392             :   {
     393             :     switch (aCause) {
     394             :       case CAUSE_KEY:
     395             :       case CAUSE_MOUSE:
     396             :       case CAUSE_TOUCH:
     397             :         return true;
     398             :       default:
     399             :         return false;
     400             :     }
     401             :   }
     402             : 
     403             :   InputContextAction()
     404             :     : mCause(CAUSE_UNKNOWN)
     405             :     , mFocusChange(FOCUS_NOT_CHANGED)
     406             :   {
     407             :   }
     408             : 
     409           8 :   explicit InputContextAction(Cause aCause,
     410             :                               FocusChange aFocusChange = FOCUS_NOT_CHANGED)
     411           8 :     : mCause(aCause)
     412           8 :     , mFocusChange(aFocusChange)
     413             :   {
     414           8 :   }
     415             : };
     416             : 
     417             : // IMEMessage is shared by IMEStateManager and TextComposition.
     418             : // Update values in GeckoEditable.java if you make changes here.
     419             : // XXX Negative values are used in Android...
     420             : typedef int8_t IMEMessageType;
     421             : enum IMEMessage : IMEMessageType
     422             : {
     423             :   // This is used by IMENotification internally.  This means that the instance
     424             :   // hasn't been initialized yet.
     425             :   NOTIFY_IME_OF_NOTHING,
     426             :   // An editable content is getting focus
     427             :   NOTIFY_IME_OF_FOCUS,
     428             :   // An editable content is losing focus
     429             :   NOTIFY_IME_OF_BLUR,
     430             :   // Selection in the focused editable content is changed
     431             :   NOTIFY_IME_OF_SELECTION_CHANGE,
     432             :   // Text in the focused editable content is changed
     433             :   NOTIFY_IME_OF_TEXT_CHANGE,
     434             :   // Notified when a dispatched composition event is handled by the
     435             :   // contents.  This must be notified after the other notifications.
     436             :   // Note that if a remote process has focus, this is notified only once when
     437             :   // all dispatched events are handled completely.  So, the receiver shouldn't
     438             :   // count number of received this notification for comparing with the number
     439             :   // of dispatched events.
     440             :   // NOTE: If a composition event causes moving focus from the focused editor,
     441             :   //       this notification may not be notified as usual.  Even in such case,
     442             :   //       NOTIFY_IME_OF_BLUR is always sent.  So, notification listeners
     443             :   //       should tread the blur notification as including this if there is
     444             :   //       pending composition events.
     445             :   NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED,
     446             :   // Position or size of focused element may be changed.
     447             :   NOTIFY_IME_OF_POSITION_CHANGE,
     448             :   // Mouse button event is fired on a character in focused editor
     449             :   NOTIFY_IME_OF_MOUSE_BUTTON_EVENT,
     450             :   // Request to commit current composition to IME
     451             :   // (some platforms may not support)
     452             :   REQUEST_TO_COMMIT_COMPOSITION,
     453             :   // Request to cancel current composition to IME
     454             :   // (some platforms may not support)
     455             :   REQUEST_TO_CANCEL_COMPOSITION
     456             : };
     457             : 
     458             : // FYI: Implemented in nsBaseWidget.cpp
     459             : const char* ToChar(IMEMessage aIMEMessage);
     460             : 
     461             : struct IMENotification final
     462             : {
     463           4 :   IMENotification()
     464           4 :     : mMessage(NOTIFY_IME_OF_NOTHING)
     465             :   {
     466           4 :   }
     467             : 
     468           0 :   IMENotification(const IMENotification& aOther)
     469           0 :     : mMessage(NOTIFY_IME_OF_NOTHING)
     470             :   {
     471           0 :     Assign(aOther);
     472           0 :   }
     473             : 
     474           0 :   ~IMENotification()
     475           0 :   {
     476           0 :     Clear();
     477           0 :   }
     478             : 
     479           0 :   MOZ_IMPLICIT IMENotification(IMEMessage aMessage)
     480           0 :     : mMessage(aMessage)
     481             :   {
     482           0 :     switch (aMessage) {
     483             :       case NOTIFY_IME_OF_SELECTION_CHANGE:
     484           0 :         mSelectionChangeData.mString = new nsString();
     485           0 :         mSelectionChangeData.Clear();
     486           0 :         break;
     487             :       case NOTIFY_IME_OF_TEXT_CHANGE:
     488           0 :         mTextChangeData.Clear();
     489           0 :         break;
     490             :       case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
     491           0 :         mMouseButtonEventData.mEventMessage = eVoidEvent;
     492           0 :         mMouseButtonEventData.mOffset = UINT32_MAX;
     493           0 :         mMouseButtonEventData.mCursorPos.Set(nsIntPoint(0, 0));
     494           0 :         mMouseButtonEventData.mCharRect.Set(nsIntRect(0, 0, 0, 0));
     495           0 :         mMouseButtonEventData.mButton = -1;
     496           0 :         mMouseButtonEventData.mButtons = 0;
     497           0 :         mMouseButtonEventData.mModifiers = 0;
     498           0 :         break;
     499             :       default:
     500           0 :         break;
     501             :     }
     502           0 :   }
     503             : 
     504           0 :   void Assign(const IMENotification& aOther)
     505             :   {
     506           0 :     bool changingMessage = mMessage != aOther.mMessage;
     507           0 :     if (changingMessage) {
     508           0 :       Clear();
     509           0 :       mMessage = aOther.mMessage;
     510             :     }
     511           0 :     switch (mMessage) {
     512             :       case NOTIFY_IME_OF_SELECTION_CHANGE:
     513           0 :         if (changingMessage) {
     514           0 :           mSelectionChangeData.mString = new nsString();
     515             :         }
     516           0 :         mSelectionChangeData.Assign(aOther.mSelectionChangeData);
     517           0 :         break;
     518             :       case NOTIFY_IME_OF_TEXT_CHANGE:
     519           0 :         mTextChangeData = aOther.mTextChangeData;
     520           0 :         break;
     521             :       case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
     522           0 :         mMouseButtonEventData = aOther.mMouseButtonEventData;
     523           0 :         break;
     524             :       default:
     525           0 :         break;
     526             :     }
     527           0 :   }
     528             : 
     529             :   IMENotification& operator=(const IMENotification& aOther)
     530             :   {
     531             :     Assign(aOther);
     532             :     return *this;
     533             :   }
     534             : 
     535           0 :   void Clear()
     536             :   {
     537           0 :     if (mMessage == NOTIFY_IME_OF_SELECTION_CHANGE) {
     538           0 :       MOZ_ASSERT(mSelectionChangeData.mString);
     539           0 :       delete mSelectionChangeData.mString;
     540           0 :       mSelectionChangeData.mString = nullptr;
     541             :     }
     542           0 :     mMessage = NOTIFY_IME_OF_NOTHING;
     543           0 :   }
     544             : 
     545           0 :   bool HasNotification() const
     546             :   {
     547           0 :     return mMessage != NOTIFY_IME_OF_NOTHING;
     548             :   }
     549             : 
     550           0 :   void MergeWith(const IMENotification& aNotification)
     551             :   {
     552           0 :     switch (mMessage) {
     553             :       case NOTIFY_IME_OF_NOTHING:
     554           0 :         MOZ_ASSERT(aNotification.mMessage != NOTIFY_IME_OF_NOTHING);
     555           0 :         Assign(aNotification);
     556           0 :         break;
     557             :       case NOTIFY_IME_OF_SELECTION_CHANGE:
     558           0 :         MOZ_ASSERT(aNotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE);
     559           0 :         mSelectionChangeData.Assign(aNotification.mSelectionChangeData);
     560           0 :         break;
     561             :       case NOTIFY_IME_OF_TEXT_CHANGE:
     562           0 :         MOZ_ASSERT(aNotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE);
     563           0 :         mTextChangeData += aNotification.mTextChangeData;
     564           0 :         break;
     565             :       case NOTIFY_IME_OF_POSITION_CHANGE:
     566             :       case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED:
     567           0 :         MOZ_ASSERT(aNotification.mMessage == mMessage);
     568           0 :         break;
     569             :       default:
     570           0 :         MOZ_CRASH("Merging notification isn't supported");
     571             :         break;
     572             :     }
     573           0 :   }
     574             : 
     575             :   IMEMessage mMessage;
     576             : 
     577             :   struct Point
     578             :   {
     579             :     int32_t mX;
     580             :     int32_t mY;
     581             : 
     582           0 :     void Set(const nsIntPoint& aPoint)
     583             :     {
     584           0 :       mX = aPoint.x;
     585           0 :       mY = aPoint.y;
     586           0 :     }
     587             :     nsIntPoint AsIntPoint() const
     588             :     {
     589             :       return nsIntPoint(mX, mY);
     590             :     }
     591             :   };
     592             : 
     593             :   struct Rect
     594             :   {
     595             :     int32_t mX;
     596             :     int32_t mY;
     597             :     int32_t mWidth;
     598             :     int32_t mHeight;
     599             : 
     600           0 :     void Set(const nsIntRect& aRect)
     601             :     {
     602           0 :       mX = aRect.x;
     603           0 :       mY = aRect.y;
     604           0 :       mWidth = aRect.width;
     605           0 :       mHeight = aRect.height;
     606           0 :     }
     607             :     nsIntRect AsIntRect() const
     608             :     {
     609             :       return nsIntRect(mX, mY, mWidth, mHeight);
     610             :     }
     611             :   };
     612             : 
     613             :   // NOTIFY_IME_OF_SELECTION_CHANGE specific data
     614           0 :   struct SelectionChangeDataBase
     615             :   {
     616             :     // Selection range.
     617             :     uint32_t mOffset;
     618             : 
     619             :     // Selected string
     620             :     nsString* mString;
     621             : 
     622             :     // Writing mode at the selection.
     623             :     uint8_t mWritingMode;
     624             : 
     625             :     bool mReversed;
     626             :     bool mCausedByComposition;
     627             :     bool mCausedBySelectionEvent;
     628             :     bool mOccurredDuringComposition;
     629             : 
     630             :     void SetWritingMode(const WritingMode& aWritingMode);
     631             :     WritingMode GetWritingMode() const;
     632             : 
     633             :     uint32_t StartOffset() const
     634             :     {
     635             :       return mOffset + (mReversed ? Length() : 0);
     636             :     }
     637             :     uint32_t EndOffset() const
     638             :     {
     639             :       return mOffset + (mReversed ? 0 : Length());
     640             :     }
     641           0 :     const nsString& String() const
     642             :     {
     643           0 :       return *mString;
     644             :     }
     645           0 :     uint32_t Length() const
     646             :     {
     647           0 :       return mString->Length();
     648             :     }
     649             :     bool IsInInt32Range() const
     650             :     {
     651             :       return mOffset + Length() <= INT32_MAX;
     652             :     }
     653           0 :     bool IsCollapsed() const
     654             :     {
     655           0 :       return mString->IsEmpty();
     656             :     }
     657           0 :     void ClearSelectionData()
     658             :     {
     659           0 :       mOffset = UINT32_MAX;
     660           0 :       mString->Truncate();
     661           0 :       mWritingMode = 0;
     662           0 :       mReversed = false;
     663           0 :     }
     664           0 :     void Clear()
     665             :     {
     666           0 :       ClearSelectionData();
     667           0 :       mCausedByComposition = false;
     668           0 :       mCausedBySelectionEvent = false;
     669           0 :       mOccurredDuringComposition = false;
     670           0 :     }
     671           0 :     bool IsValid() const
     672             :     {
     673           0 :       return mOffset != UINT32_MAX;
     674             :     }
     675           0 :     void Assign(const SelectionChangeDataBase& aOther)
     676             :     {
     677           0 :       mOffset = aOther.mOffset;
     678           0 :       *mString = aOther.String();
     679           0 :       mWritingMode = aOther.mWritingMode;
     680           0 :       mReversed = aOther.mReversed;
     681           0 :       AssignReason(aOther.mCausedByComposition,
     682           0 :                    aOther.mCausedBySelectionEvent,
     683           0 :                    aOther.mOccurredDuringComposition);
     684           0 :     }
     685           0 :     void AssignReason(bool aCausedByComposition,
     686             :                       bool aCausedBySelectionEvent,
     687             :                       bool aOccurredDuringComposition)
     688             :     {
     689           0 :       mCausedByComposition = aCausedByComposition;
     690           0 :       mCausedBySelectionEvent = aCausedBySelectionEvent;
     691           0 :       mOccurredDuringComposition = aOccurredDuringComposition;
     692           0 :     }
     693             :   };
     694             : 
     695             :   // SelectionChangeDataBase cannot have constructors because it's used in
     696             :   // the union.  Therefore, SelectionChangeData should only implement
     697             :   // constructors.  In other words, add other members to
     698             :   // SelectionChangeDataBase.
     699           0 :   struct SelectionChangeData final : public SelectionChangeDataBase
     700             :   {
     701           0 :     SelectionChangeData()
     702           0 :     {
     703           0 :       mString = &mStringInstance;
     704           0 :       Clear();
     705           0 :     }
     706             :     explicit SelectionChangeData(const SelectionChangeDataBase& aOther)
     707             :     {
     708             :       mString = &mStringInstance;
     709             :       Assign(aOther);
     710             :     }
     711           0 :     SelectionChangeData(const SelectionChangeData& aOther)
     712           0 :     {
     713           0 :       mString = &mStringInstance;
     714           0 :       Assign(aOther);
     715           0 :     }
     716             :     SelectionChangeData& operator=(const SelectionChangeDataBase& aOther)
     717             :     {
     718             :       mString = &mStringInstance;
     719             :       Assign(aOther);
     720             :       return *this;
     721             :     }
     722             :     SelectionChangeData& operator=(const SelectionChangeData& aOther)
     723             :     {
     724             :       mString = &mStringInstance;
     725             :       Assign(aOther);
     726             :       return *this;
     727             :     }
     728             : 
     729             :   private:
     730             :     // When SelectionChangeData is used outside of union, it shouldn't create
     731             :     // nsString instance in the heap as far as possible.
     732             :     nsString mStringInstance;
     733             :   };
     734             : 
     735           0 :   struct TextChangeDataBase
     736             :   {
     737             :     // mStartOffset is the start offset of modified or removed text in
     738             :     // original content and inserted text in new content.
     739             :     uint32_t mStartOffset;
     740             :     // mRemovalEndOffset is the end offset of modified or removed text in
     741             :     // original content.  If the value is same as mStartOffset, no text hasn't
     742             :     // been removed yet.
     743             :     uint32_t mRemovedEndOffset;
     744             :     // mAddedEndOffset is the end offset of inserted text or same as
     745             :     // mStartOffset if just removed.  The vlaue is offset in the new content.
     746             :     uint32_t mAddedEndOffset;
     747             : 
     748             :     // Note that TextChangeDataBase may be the result of merging two or more
     749             :     // changes especially in e10s mode.
     750             : 
     751             :     // mCausedOnlyByComposition is true only when *all* merged changes are
     752             :     // caused by composition.
     753             :     bool mCausedOnlyByComposition;
     754             :     // mIncludingChangesDuringComposition is true if at least one change which
     755             :     // is not caused by composition occurred during the last composition.
     756             :     // Note that if after the last composition is finished and there are some
     757             :     // changes not caused by composition, this is set to false.
     758             :     bool mIncludingChangesDuringComposition;
     759             :     // mIncludingChangesWithoutComposition is true if there is at least one
     760             :     // change which did occur when there wasn't a composition ongoing.
     761             :     bool mIncludingChangesWithoutComposition;
     762             : 
     763           0 :     uint32_t OldLength() const
     764             :     {
     765           0 :       MOZ_ASSERT(IsValid());
     766           0 :       return mRemovedEndOffset - mStartOffset;
     767             :     }
     768           0 :     uint32_t NewLength() const
     769             :     {
     770           0 :       MOZ_ASSERT(IsValid());
     771           0 :       return mAddedEndOffset - mStartOffset;
     772             :     }
     773             : 
     774             :     // Positive if text is added. Negative if text is removed.
     775           0 :     int64_t Difference() const 
     776             :     {
     777           0 :       return mAddedEndOffset - mRemovedEndOffset;
     778             :     }
     779             : 
     780             :     bool IsInInt32Range() const
     781             :     {
     782             :       MOZ_ASSERT(IsValid());
     783             :       return mStartOffset <= INT32_MAX &&
     784             :              mRemovedEndOffset <= INT32_MAX &&
     785             :              mAddedEndOffset <= INT32_MAX;
     786             :     }
     787             : 
     788           0 :     bool IsValid() const
     789             :     {
     790           0 :       return !(mStartOffset == UINT32_MAX &&
     791           0 :                !mRemovedEndOffset && !mAddedEndOffset);
     792             :     }
     793             : 
     794           0 :     void Clear()
     795             :     {
     796           0 :       mStartOffset = UINT32_MAX;
     797           0 :       mRemovedEndOffset = mAddedEndOffset = 0;
     798           0 :     }
     799             : 
     800             :     void MergeWith(const TextChangeDataBase& aOther);
     801           0 :     TextChangeDataBase& operator+=(const TextChangeDataBase& aOther)
     802             :     {
     803           0 :       MergeWith(aOther);
     804           0 :       return *this;
     805             :     }
     806             : 
     807             : #ifdef DEBUG
     808             :     void Test();
     809             : #endif // #ifdef DEBUG
     810             :   };
     811             : 
     812             :   // TextChangeDataBase cannot have constructors because they are used in union.
     813             :   // Therefore, TextChangeData should only implement constructor.  In other
     814             :   // words, add other members to TextChangeDataBase.
     815             :   struct TextChangeData : public TextChangeDataBase
     816             :   {
     817           0 :     TextChangeData() { Clear(); }
     818             : 
     819           0 :     TextChangeData(uint32_t aStartOffset,
     820             :                    uint32_t aRemovedEndOffset,
     821             :                    uint32_t aAddedEndOffset,
     822             :                    bool aCausedByComposition,
     823             :                    bool aOccurredDuringComposition)
     824           0 :     {
     825           0 :       MOZ_ASSERT(aRemovedEndOffset >= aStartOffset,
     826             :                  "removed end offset must not be smaller than start offset");
     827           0 :       MOZ_ASSERT(aAddedEndOffset >= aStartOffset,
     828             :                  "added end offset must not be smaller than start offset");
     829           0 :       mStartOffset = aStartOffset;
     830           0 :       mRemovedEndOffset = aRemovedEndOffset;
     831           0 :       mAddedEndOffset = aAddedEndOffset;
     832           0 :       mCausedOnlyByComposition = aCausedByComposition;
     833           0 :       mIncludingChangesDuringComposition =
     834           0 :         !aCausedByComposition && aOccurredDuringComposition;
     835           0 :       mIncludingChangesWithoutComposition =
     836           0 :         !aCausedByComposition && !aOccurredDuringComposition;
     837           0 :     }
     838             :   };
     839             : 
     840             :   struct MouseButtonEventData
     841             :   {
     842             :     // The value of WidgetEvent::mMessage
     843             :     EventMessage mEventMessage;
     844             :     // Character offset from the start of the focused editor under the cursor
     845             :     uint32_t mOffset;
     846             :     // Cursor position in pixels relative to the widget
     847             :     Point mCursorPos;
     848             :     // Character rect in pixels under the cursor relative to the widget
     849             :     Rect mCharRect;
     850             :     // The value of WidgetMouseEventBase::button and buttons
     851             :     int16_t mButton;
     852             :     int16_t mButtons;
     853             :     // The value of WidgetInputEvent::modifiers
     854             :     Modifiers mModifiers;
     855             :   };
     856             : 
     857             :   union
     858             :   {
     859             :     // NOTIFY_IME_OF_SELECTION_CHANGE specific data
     860             :     SelectionChangeDataBase mSelectionChangeData;
     861             : 
     862             :     // NOTIFY_IME_OF_TEXT_CHANGE specific data
     863             :     TextChangeDataBase mTextChangeData;
     864             : 
     865             :     // NOTIFY_IME_OF_MOUSE_BUTTON_EVENT specific data
     866             :     MouseButtonEventData mMouseButtonEventData;
     867             :   };
     868             : 
     869           0 :   void SetData(const SelectionChangeDataBase& aSelectionChangeData)
     870             :   {
     871           0 :     MOZ_RELEASE_ASSERT(mMessage == NOTIFY_IME_OF_SELECTION_CHANGE);
     872           0 :     mSelectionChangeData.Assign(aSelectionChangeData);
     873           0 :   }
     874             : 
     875           0 :   void SetData(const TextChangeDataBase& aTextChangeData)
     876             :   {
     877           0 :     MOZ_RELEASE_ASSERT(mMessage == NOTIFY_IME_OF_TEXT_CHANGE);
     878           0 :     mTextChangeData = aTextChangeData;
     879           0 :   }
     880             : };
     881             : 
     882           0 : struct CandidateWindowPosition
     883             : {
     884             :   // Upper left corner of the candidate window if mExcludeRect is false.
     885             :   // Otherwise, the position currently interested.  E.g., caret position.
     886             :   LayoutDeviceIntPoint mPoint;
     887             :   // Rect which shouldn't be overlapped with the candidate window.
     888             :   // This is valid only when mExcludeRect is true.
     889             :   LayoutDeviceIntRect mRect;
     890             :   // See explanation of mPoint and mRect.
     891             :   bool mExcludeRect;
     892             : };
     893             : 
     894             : } // namespace widget
     895             : } // namespace mozilla
     896             : 
     897             : #endif // #ifndef mozilla_widget_IMEData_h_

Generated by: LCOV version 1.13