LCOV - code coverage report
Current view: top level - dom/events - IMEStateManager.h (source / functions) Hit Total Coverage
Test: output.info Lines: 2 17 11.8 %
Date: 2017-07-14 16:53:18 Functions: 1 5 20.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_IMEStateManager_h_
       8             : #define mozilla_IMEStateManager_h_
       9             : 
      10             : #include "mozilla/EventForwards.h"
      11             : #include "mozilla/StaticPtr.h"
      12             : #include "mozilla/dom/TabParent.h"
      13             : #include "nsIWidget.h"
      14             : 
      15             : class nsIContent;
      16             : class nsINode;
      17             : class nsPresContext;
      18             : class nsISelection;
      19             : 
      20             : namespace mozilla {
      21             : 
      22             : class EditorBase;
      23             : class EventDispatchingCallback;
      24             : class IMEContentObserver;
      25             : class TextCompositionArray;
      26             : class TextComposition;
      27             : 
      28             : /**
      29             :  * IMEStateManager manages InputContext (e.g., active editor type, IME enabled
      30             :  * state and IME open state) of nsIWidget instances, manages IMEContentObserver
      31             :  * and provides useful API for IME.
      32             :  */
      33             : 
      34             : class IMEStateManager
      35             : {
      36             :   typedef dom::TabParent TabParent;
      37             :   typedef widget::IMEMessage IMEMessage;
      38             :   typedef widget::IMENotification IMENotification;
      39             :   typedef widget::IMEState IMEState;
      40             :   typedef widget::InputContext InputContext;
      41             :   typedef widget::InputContextAction InputContextAction;
      42             : 
      43             : public:
      44             :   static void Init();
      45             :   static void Shutdown();
      46             : 
      47             :   /**
      48             :    * GetActiveTabParent() returns a pointer to a TabParent instance which is
      49             :    * managed by the focused content (sContent).  If the focused content isn't
      50             :    * managing another process, this returns nullptr.
      51             :    */
      52           0 :   static TabParent* GetActiveTabParent()
      53             :   {
      54             :     // If menu has pseudo focus, we should ignore active child process.
      55           0 :     if (sInstalledMenuKeyboardListener) {
      56           0 :       return nullptr;
      57             :     }
      58           0 :     return sActiveTabParent.get();
      59             :   }
      60             : 
      61             :   /**
      62             :    * DoesTabParentHaveIMEFocus() returns true when aTabParent has IME focus,
      63             :    * i.e., the TabParent sent "focus" notification but not yet sends "blur".
      64             :    * Note that this doesn't check if the remote processes are same because
      65             :    * if another TabParent has focus, committing composition causes firing
      66             :    * composition events in different TabParent.  (Anyway, such case shouldn't
      67             :    * occur.)
      68             :    */
      69           0 :   static bool DoesTabParentHaveIMEFocus(const TabParent* aTabParent)
      70             :   {
      71           0 :     MOZ_ASSERT(aTabParent);
      72           0 :     return sFocusedIMETabParent == aTabParent;
      73             :   }
      74             : 
      75             :   /**
      76             :    * OnTabParentDestroying() is called when aTabParent is being destroyed.
      77             :    */
      78             :   static void OnTabParentDestroying(TabParent* aTabParent);
      79             : 
      80             :   /**
      81             :    * Called when aWidget is being deleted.
      82             :    */
      83             :   static void WidgetDestroyed(nsIWidget* aWidget);
      84             : 
      85             :   /**
      86             :    * GetWidgetForActiveInputContext() returns a widget which IMEStateManager
      87             :    * is managing input context with.  If a widget instance needs to cache
      88             :    * the last input context for nsIWidget::GetInputContext() or something,
      89             :    * it should check if its cache is valid with this method before using it
      90             :    * because if this method returns another instance, it means that
      91             :    * IMEStateManager may have already changed shared input context via the
      92             :    * widget.
      93             :    */
      94           1 :   static nsIWidget* GetWidgetForActiveInputContext()
      95             :   {
      96           1 :     return sActiveInputContextWidget;
      97             :   }
      98             : 
      99             :   /**
     100             :    * SetIMEContextForChildProcess() is called when aTabParent receives
     101             :    * SetInputContext() from the remote process.
     102             :    */
     103             :   static void SetInputContextForChildProcess(TabParent* aTabParent,
     104             :                                              const InputContext& aInputContext,
     105             :                                              const InputContextAction& aAction);
     106             : 
     107             :   /**
     108             :    * StopIMEStateManagement() is called when the process should stop managing
     109             :    * IME state.
     110             :    */
     111             :   static void StopIMEStateManagement();
     112             : 
     113             :   /**
     114             :    * MaybeStartOffsetUpdatedInChild() is called when composition start offset
     115             :    * is maybe updated in the child process.  I.e., even if it's not updated,
     116             :    * this is called and never called if the composition is in this process.
     117             :    * @param aWidget             The widget whose native IME context has the
     118             :    *                            composition.
     119             :    * @param aStartOffset        New composition start offset with native
     120             :    *                            linebreaks.
     121             :    */
     122             :   static void MaybeStartOffsetUpdatedInChild(nsIWidget* aWidget,
     123             :                                              uint32_t aStartOffset);
     124             : 
     125             :   static nsresult OnDestroyPresContext(nsPresContext* aPresContext);
     126             :   static nsresult OnRemoveContent(nsPresContext* aPresContext,
     127             :                                   nsIContent* aContent);
     128             :   /**
     129             :    * OnChangeFocus() should be called when focused content is changed or
     130             :    * IME enabled state is changed.  If nobody has focus, set both aPresContext
     131             :    * and aContent nullptr.  E.g., all windows are deactivated.
     132             :    */
     133             :   static nsresult OnChangeFocus(nsPresContext* aPresContext,
     134             :                                 nsIContent* aContent,
     135             :                                 InputContextAction::Cause aCause);
     136             :   static void OnInstalledMenuKeyboardListener(bool aInstalling);
     137             : 
     138             :   // These two methods manage focus and selection/text observers.
     139             :   // They are separate from OnChangeFocus above because this offers finer
     140             :   // control compared to having the two methods incorporated into OnChangeFocus
     141             : 
     142             :   // Get the focused editor's selection and root
     143             :   static nsresult GetFocusSelectionAndRoot(nsISelection** aSel,
     144             :                                            nsIContent** aRoot);
     145             :   // This method updates the current IME state.  However, if the enabled state
     146             :   // isn't changed by the new state, this method does nothing.
     147             :   // Note that this method changes the IME state of the active element in the
     148             :   // widget.  So, the caller must have focus.
     149             :   static void UpdateIMEState(const IMEState &aNewIMEState,
     150             :                              nsIContent* aContent,
     151             :                              EditorBase& aEditorBase);
     152             : 
     153             :   // This method is called when user operates mouse button in focused editor
     154             :   // and before the editor handles it.
     155             :   // Returns true if IME consumes the event.  Otherwise, false.
     156             :   static bool OnMouseButtonEventInEditor(nsPresContext* aPresContext,
     157             :                                          nsIContent* aContent,
     158             :                                          WidgetMouseEvent* aMouseEvent);
     159             : 
     160             :   // This method is called when user clicked in an editor.
     161             :   // aContent must be:
     162             :   //   If the editor is for <input> or <textarea>, the element.
     163             :   //   If the editor is for contenteditable, the active editinghost.
     164             :   //   If the editor is for designMode, nullptr.
     165             :   static void OnClickInEditor(nsPresContext* aPresContext,
     166             :                               nsIContent* aContent,
     167             :                               const WidgetMouseEvent* aMouseEvent);
     168             : 
     169             :   // This method is called when editor actually gets focus.
     170             :   // aContent must be:
     171             :   //   If the editor is for <input> or <textarea>, the element.
     172             :   //   If the editor is for contenteditable, the active editinghost.
     173             :   //   If the editor is for designMode, nullptr.
     174             :   static void OnFocusInEditor(nsPresContext* aPresContext,
     175             :                               nsIContent* aContent,
     176             :                               EditorBase& aEditorBase);
     177             : 
     178             :   // This method is called when the editor is initialized.
     179             :   static void OnEditorInitialized(EditorBase& aEditorBase);
     180             : 
     181             :   // This method is called when the editor is (might be temporarily) being
     182             :   // destroyed.
     183             :   static void OnEditorDestroying(EditorBase& aEditorBase);
     184             : 
     185             :   /**
     186             :    * All composition events must be dispatched via DispatchCompositionEvent()
     187             :    * for storing the composition target and ensuring a set of composition
     188             :    * events must be fired the stored target.  If the stored composition event
     189             :    * target is destroying, this removes the stored composition automatically.
     190             :    */
     191             :   static void DispatchCompositionEvent(
     192             :                 nsINode* aEventTargetNode,
     193             :                 nsPresContext* aPresContext,
     194             :                 WidgetCompositionEvent* aCompositionEvent,
     195             :                 nsEventStatus* aStatus,
     196             :                 EventDispatchingCallback* aCallBack,
     197             :                 bool aIsSynthesized = false);
     198             : 
     199             :   /**
     200             :    * All selection events must be handled via HandleSelectionEvent()
     201             :    * because they must be handled by same target as composition events when
     202             :    * there is a composition.
     203             :    */
     204             :   static void HandleSelectionEvent(nsPresContext* aPresContext,
     205             :                                    nsIContent* aEventTargetContent,
     206             :                                    WidgetSelectionEvent* aSelectionEvent);
     207             : 
     208             :   /**
     209             :    * This is called when PresShell ignores a composition event due to not safe
     210             :    * to dispatch events.
     211             :    */
     212             :   static void OnCompositionEventDiscarded(
     213             :                 WidgetCompositionEvent* aCompositionEvent);
     214             : 
     215             :   /**
     216             :    * Get TextComposition from widget.
     217             :    */
     218             :   static already_AddRefed<TextComposition>
     219             :     GetTextCompositionFor(nsIWidget* aWidget);
     220             : 
     221             :   /**
     222             :    * Returns TextComposition instance for the event.
     223             :    */
     224             :   static already_AddRefed<TextComposition>
     225             :     GetTextCompositionFor(const WidgetCompositionEvent* aCompositionEvent);
     226             : 
     227             :   /**
     228             :    * Returns TextComposition instance for the pres context.
     229             :    * Be aware, even if another pres context which shares native IME context with
     230             :    * specified pres context has composition, this returns nullptr.
     231             :    */
     232             :   static already_AddRefed<TextComposition>
     233             :     GetTextCompositionFor(nsPresContext* aPresContext);
     234             : 
     235             :   /**
     236             :    * Send a notification to IME.  It depends on the IME or platform spec what
     237             :    * will occur (or not occur).
     238             :    */
     239             :   static nsresult NotifyIME(const IMENotification& aNotification,
     240             :                             nsIWidget* aWidget,
     241             :                             TabParent* aTabParent = nullptr);
     242             :   static nsresult NotifyIME(IMEMessage aMessage,
     243             :                             nsIWidget* aWidget,
     244             :                             TabParent* aTabParent = nullptr);
     245             :   static nsresult NotifyIME(IMEMessage aMessage,
     246             :                             nsPresContext* aPresContext,
     247             :                             TabParent* aTabParent = nullptr);
     248             : 
     249             :   static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
     250             :                                       nsIContent* aContent);
     251             : 
     252             :   /**
     253             :    * Returns active IMEContentObserver but may be nullptr if focused content
     254             :    * isn't editable or focus in a remote process.
     255             :    */
     256             :   static IMEContentObserver* GetActiveContentObserver();
     257             : 
     258             : protected:
     259             :   static nsresult OnChangeFocusInternal(nsPresContext* aPresContext,
     260             :                                         nsIContent* aContent,
     261             :                                         InputContextAction aAction);
     262             :   static void SetIMEState(const IMEState &aState,
     263             :                           nsIContent* aContent,
     264             :                           nsIWidget* aWidget,
     265             :                           InputContextAction aAction,
     266             :                           InputContext::Origin aOrigin);
     267             :   static void SetInputContext(nsIWidget* aWidget,
     268             :                               const InputContext& aInputContext,
     269             :                               const InputContextAction& aAction);
     270             :   static IMEState GetNewIMEState(nsPresContext* aPresContext,
     271             :                                  nsIContent* aContent);
     272             : 
     273             :   static void EnsureTextCompositionArray();
     274             :   static void CreateIMEContentObserver(EditorBase* aEditorBase);
     275             :   static void DestroyIMEContentObserver();
     276             : 
     277             :   static bool IsEditable(nsINode* node);
     278             : 
     279             :   static bool IsIMEObserverNeeded(const IMEState& aState);
     280             : 
     281             :   static nsIContent* GetRootContent(nsPresContext* aPresContext);
     282             : 
     283             :   /**
     284             :    * CanHandleWith() returns false if aPresContext is nullptr or it's destroyed.
     285             :    */
     286             :   static bool CanHandleWith(nsPresContext* aPresContext);
     287             : 
     288             :   // sContent and sPresContext are the focused content and PresContext.  If a
     289             :   // document has focus but there is no focused element, sContent may be
     290             :   // nullptr.
     291             :   static StaticRefPtr<nsIContent> sContent;
     292             :   static StaticRefPtr<nsPresContext> sPresContext;
     293             :   // sWidget is cache for the root widget of sPresContext.  Even afer
     294             :   // sPresContext has gone, we need to clean up some IME state on the widget
     295             :   // if the widget is available.
     296             :   static nsIWidget* sWidget;
     297             :   // sFocusedIMETabParent is the tab parent, which send "focus" notification to
     298             :   // sFocusedIMEWidget (and didn't yet sent "blur" notification).
     299             :   static nsIWidget* sFocusedIMEWidget;
     300             :   static StaticRefPtr<TabParent> sFocusedIMETabParent;
     301             :   // sActiveInputContextWidget is the last widget whose SetInputContext() is
     302             :   // called.  This is important to reduce sync IPC cost with parent process.
     303             :   // If IMEStateManager set input context to different widget, PuppetWidget can
     304             :   // return cached input context safely.
     305             :   static nsIWidget* sActiveInputContextWidget;
     306             :   static StaticRefPtr<TabParent> sActiveTabParent;
     307             :   // sActiveIMEContentObserver points to the currently active
     308             :   // IMEContentObserver.  This is null if there is no focused editor.
     309             :   static StaticRefPtr<IMEContentObserver> sActiveIMEContentObserver;
     310             : 
     311             :   // All active compositions in the process are stored by this array.
     312             :   // When you get an item of this array and use it, please be careful.
     313             :   // The instances in this array can be destroyed automatically if you do
     314             :   // something to cause committing or canceling the composition.
     315             :   static TextCompositionArray* sTextCompositions;
     316             : 
     317             :   // Origin type of current process.
     318             :   static InputContext::Origin sOrigin;
     319             : 
     320             :   static bool           sInstalledMenuKeyboardListener;
     321             :   static bool           sIsGettingNewIMEState;
     322             :   static bool           sCheckForIMEUnawareWebApps;
     323             :   static bool           sInputModeSupported;
     324             : 
     325             :   class MOZ_STACK_CLASS GettingNewIMEStateBlocker final
     326             :   {
     327             :   public:
     328           0 :     GettingNewIMEStateBlocker()
     329           0 :       : mOldValue(IMEStateManager::sIsGettingNewIMEState)
     330             :     {
     331           0 :       IMEStateManager::sIsGettingNewIMEState = true;
     332           0 :     }
     333           0 :     ~GettingNewIMEStateBlocker()
     334           0 :     {
     335           0 :       IMEStateManager::sIsGettingNewIMEState = mOldValue;
     336           0 :     }
     337             :   private:
     338             :     bool mOldValue;
     339             :   };
     340             : };
     341             : 
     342             : } // namespace mozilla
     343             : 
     344             : #endif // mozilla_IMEStateManager_h_

Generated by: LCOV version 1.13