dom/events/TextComposition.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 sw=2 et 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/. */
     7 #ifndef mozilla_TextComposition_h
     8 #define mozilla_TextComposition_h
    10 #include "nsCOMPtr.h"
    11 #include "nsINode.h"
    12 #include "nsIWeakReference.h"
    13 #include "nsIWidget.h"
    14 #include "nsTArray.h"
    15 #include "nsThreadUtils.h"
    16 #include "nsPresContext.h"
    17 #include "mozilla/Attributes.h"
    18 #include "mozilla/EventForwards.h"
    19 #include "mozilla/TextRange.h"
    21 class nsIEditor;
    23 namespace mozilla {
    25 class EventDispatchingCallback;
    26 class IMEStateManager;
    28 /**
    29  * TextComposition represents a text composition.  This class stores the
    30  * composition event target and its presContext.  At dispatching the event via
    31  * this class, the instances use the stored event target.
    32  */
    34 class TextComposition MOZ_FINAL
    35 {
    36   friend class IMEStateManager;
    38   NS_INLINE_DECL_REFCOUNTING(TextComposition)
    40 public:
    41   TextComposition(nsPresContext* aPresContext,
    42                   nsINode* aNode,
    43                   WidgetGUIEvent* aEvent);
    45   bool Destroyed() const { return !mPresContext; }
    46   nsPresContext* GetPresContext() const { return mPresContext; }
    47   nsINode* GetEventTargetNode() const { return mNode; }
    48   // The latest CompositionEvent.data value except compositionstart event.
    49   // This value is modified at dispatching compositionupdate.
    50   const nsString& LastData() const { return mLastData; }
    51   // The composition string which is already handled by the focused editor.
    52   // I.e., this value must be same as the composition string on the focused
    53   // editor.  This value is modified at a call of EditorDidHandleTextEvent().
    54   // Note that mString and mLastData are different between dispatcing
    55   // compositionupdate and text event handled by focused editor.
    56   const nsString& String() const { return mString; }
    57   // Returns the clauses and/or caret range of the composition string.
    58   // This is modified at a call of EditorWillHandleTextEvent().
    59   // This may return null if there is no clauses and caret.
    60   // XXX We should return |const TextRangeArray*| here, but it causes compile
    61   //     error due to inaccessible Release() method.
    62   TextRangeArray* GetRanges() const { return mRanges; }
    63   // Returns true if the composition is started with synthesized event which
    64   // came from nsDOMWindowUtils.
    65   bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
    67   bool MatchesNativeContext(nsIWidget* aWidget) const;
    69   /**
    70    * This is called when IMEStateManager stops managing the instance.
    71    */
    72   void Destroy();
    74   /**
    75    * SynthesizeCommit() dispatches compositionupdate, text and compositionend
    76    * events for emulating commit on the content.
    77    *
    78    * @param aDiscard true when committing with empty string.  Otherwise, false.
    79    */
    80   void SynthesizeCommit(bool aDiscard);
    82   /**
    83    * Send a notification to IME.  It depends on the IME or platform spec what
    84    * will occur (or not occur).
    85    */
    86   nsresult NotifyIME(widget::IMEMessage aMessage);
    88   /**
    89    * the offset of first selected clause or start of of compositon
    90    */
    91   uint32_t OffsetOfTargetClause() const { return mCompositionTargetOffset; }
    93   /**
    94    * Returns true if there is non-empty composition string and it's not fixed.
    95    * Otherwise, false.
    96    */
    97   bool IsComposing() const { return mIsComposing; }
    99   /**
   100    * Returns true while editor is handling an event which is modifying the
   101    * composition string.
   102    */
   103   bool IsEditorHandlingEvent() const
   104   {
   105     return mIsEditorHandlingEvent;
   106   }
   108   /**
   109    * StartHandlingComposition() and EndHandlingComposition() are called by
   110    * editor when it holds a TextComposition instance and release it.
   111    */
   112   void StartHandlingComposition(nsIEditor* aEditor);
   113   void EndHandlingComposition(nsIEditor* aEditor);
   115   /**
   116    * TextEventHandlingMarker class should be created at starting to handle text
   117    * event in focused editor.  This calls EditorWillHandleTextEvent() and
   118    * EditorDidHandleTextEvent() automatically.
   119    */
   120   class MOZ_STACK_CLASS TextEventHandlingMarker
   121   {
   122   public:
   123     TextEventHandlingMarker(TextComposition* aComposition,
   124                             const WidgetTextEvent* aTextEvent)
   125       : mComposition(aComposition)
   126     {
   127       mComposition->EditorWillHandleTextEvent(aTextEvent);
   128     }
   130     ~TextEventHandlingMarker()
   131     {
   132       mComposition->EditorDidHandleTextEvent();
   133     }
   135   private:
   136     nsRefPtr<TextComposition> mComposition;
   137     TextEventHandlingMarker();
   138     TextEventHandlingMarker(const TextEventHandlingMarker& aOther);
   139   };
   141 private:
   142   // Private destructor, to discourage deletion outside of Release():
   143   ~TextComposition()
   144   {
   145     // WARNING: mPresContext may be destroying, so, be careful if you touch it.
   146   }
   148   // This class holds nsPresContext weak.  This instance shouldn't block
   149   // destroying it.  When the presContext is being destroyed, it's notified to
   150   // IMEStateManager::OnDestroyPresContext(), and then, it destroy
   151   // this instance.
   152   nsPresContext* mPresContext;
   153   nsCOMPtr<nsINode> mNode;
   155   // This is the clause and caret range information which is managed by
   156   // the focused editor.  This may be null if there is no clauses or caret.
   157   nsRefPtr<TextRangeArray> mRanges;
   159   // mNativeContext stores a opaque pointer.  This works as the "ID" for this
   160   // composition.  Don't access the instance, it may not be available.
   161   void* mNativeContext;
   163   // mEditorWeak is a weak reference to the focused editor handling composition.
   164   nsWeakPtr mEditorWeak;
   166   // mLastData stores the data attribute of the latest composition event (except
   167   // the compositionstart event).
   168   nsString mLastData;
   170   // mString stores the composition text which has been handled by the focused
   171   // editor.
   172   nsString mString;
   174   // Offset of the composition string from start of the editor
   175   uint32_t mCompositionStartOffset;
   176   // Offset of the selected clause of the composition string from start of the
   177   // editor
   178   uint32_t mCompositionTargetOffset;
   180   // See the comment for IsSynthesizedForTests().
   181   bool mIsSynthesizedForTests;
   183   // See the comment for IsComposing().
   184   bool mIsComposing;
   186   // mIsEditorHandlingEvent is true while editor is modifying the composition
   187   // string.
   188   bool mIsEditorHandlingEvent;
   190   // Hide the default constructor and copy constructor.
   191   TextComposition() {}
   192   TextComposition(const TextComposition& aOther);
   194   /**
   195    * GetEditor() returns nsIEditor pointer of mEditorWeak.
   196    */
   197   already_AddRefed<nsIEditor> GetEditor() const;
   199   /**
   200    * HasEditor() returns true if mEditorWeak holds nsIEditor instance which is
   201    * alive.  Otherwise, false.
   202    */
   203   bool HasEditor() const;
   205   /**
   206    * EditorWillHandleTextEvent() must be called before the focused editor
   207    * handles the text event.
   208    */
   209   void EditorWillHandleTextEvent(const WidgetTextEvent* aTextEvent);
   211   /**
   212    * EditorDidHandleTextEvent() must be called after the focused editor handles
   213    * a text event.
   214    */
   215   void EditorDidHandleTextEvent();
   217   /**
   218    * DispatchEvent() dispatches the aEvent to the mContent synchronously.
   219    * The caller must ensure that it's safe to dispatch the event.
   220    */
   221   void DispatchEvent(WidgetGUIEvent* aEvent,
   222                      nsEventStatus* aStatus,
   223                      EventDispatchingCallback* aCallBack);
   225   /**
   226    * Calculate composition offset then notify composition update to widget
   227    */
   228   void NotityUpdateComposition(WidgetGUIEvent* aEvent);
   230   /**
   231    * CompositionEventDispatcher dispatches the specified composition (or text)
   232    * event.
   233    */
   234   class CompositionEventDispatcher : public nsRunnable
   235   {
   236   public:
   237     CompositionEventDispatcher(nsPresContext* aPresContext,
   238                                nsINode* aEventTarget,
   239                                uint32_t aEventMessage,
   240                                const nsAString& aData);
   241     NS_IMETHOD Run() MOZ_OVERRIDE;
   243   private:
   244     nsRefPtr<nsPresContext> mPresContext;
   245     nsCOMPtr<nsINode> mEventTarget;
   246     nsCOMPtr<nsIWidget> mWidget;
   247     uint32_t mEventMessage;
   248     nsString mData;
   250     CompositionEventDispatcher() {};
   251   };
   253   /**
   254    * DispatchCompositionEventRunnable() dispatches a composition or text event
   255    * to the content.  Be aware, if you use this method, nsPresShellEventCB
   256    * isn't used.  That means that nsIFrame::HandleEvent() is never called.
   257    * WARNING: The instance which is managed by IMEStateManager may be
   258    *          destroyed by this method call.
   259    *
   260    * @param aEventMessage       Must be one of composition event or text event.
   261    * @param aData               Used for data value if aEventMessage is
   262    *                            NS_COMPOSITION_UPDATE or NS_COMPOSITION_END.
   263    *                            Used for theText value if aEventMessage is
   264    *                            NS_TEXT_TEXT.
   265    */
   266   void DispatchCompositionEventRunnable(uint32_t aEventMessage,
   267                                         const nsAString& aData);
   268 };
   270 /**
   271  * TextCompositionArray manages the instances of TextComposition class.
   272  * Managing with array is enough because only one composition is typically
   273  * there.  Even if user switches native IME context, it's very rare that
   274  * second or more composition is started.
   275  * It's assumed that this is used by IMEStateManager for storing all active
   276  * compositions in the process.  If the instance is it, each TextComposition
   277  * in the array can be destroyed by calling some methods of itself.
   278  */
   280 class TextCompositionArray MOZ_FINAL :
   281   public nsAutoTArray<nsRefPtr<TextComposition>, 2>
   282 {
   283 public:
   284   index_type IndexOf(nsIWidget* aWidget);
   285   index_type IndexOf(nsPresContext* aPresContext);
   286   index_type IndexOf(nsPresContext* aPresContext, nsINode* aNode);
   288   TextComposition* GetCompositionFor(nsIWidget* aWidget);
   289   TextComposition* GetCompositionFor(nsPresContext* aPresContext,
   290                                      nsINode* aNode);
   291   TextComposition* GetCompositionInContent(nsPresContext* aPresContext,
   292                                            nsIContent* aContent);
   293 };
   295 } // namespace mozilla
   297 #endif // #ifndef mozilla_TextComposition_h

mercurial