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_IMEContentObserver_h_
8 #define mozilla_IMEContentObserver_h_
10 #include "mozilla/Attributes.h"
12 #include "nsCycleCollectionParticipant.h"
13 #include "nsIDocShell.h" // XXX Why does only this need to be included here?
14 #include "nsIEditor.h"
15 #include "nsIEditorObserver.h"
16 #include "nsIReflowObserver.h"
17 #include "nsISelectionListener.h"
18 #include "nsIScrollObserver.h"
19 #include "nsIWidget.h" // for nsIMEUpdatePreference
20 #include "nsStubMutationObserver.h"
21 #include "nsWeakReference.h"
30 class EventStateManager
;
32 // IMEContentObserver notifies widget of any text and selection changes
33 // in the currently focused editor
34 class IMEContentObserver MOZ_FINAL
: public nsISelectionListener
35 , public nsStubMutationObserver
36 , public nsIReflowObserver
37 , public nsIScrollObserver
38 , public nsSupportsWeakReference
39 , public nsIEditorObserver
41 friend class AsyncMergeableNotificationsFlusher
;
46 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
47 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IMEContentObserver
,
49 NS_DECL_NSIEDITOROBSERVER
50 NS_DECL_NSISELECTIONLISTENER
51 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATAWILLCHANGE
52 NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
53 NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
54 NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
55 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
56 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
57 NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
58 NS_DECL_NSIREFLOWOBSERVER
61 virtual void ScrollPositionChanged() MOZ_OVERRIDE
;
63 bool OnMouseButtonEvent(nsPresContext
* aPresContext
,
64 WidgetMouseEvent
* aMouseEvent
);
66 void Init(nsIWidget
* aWidget
, nsPresContext
* aPresContext
,
67 nsIContent
* aContent
);
70 * IMEContentObserver is stored by EventStateManager during observing.
71 * DisconnectFromEventStateManager() is called when EventStateManager stops
72 * storing the instance.
74 void DisconnectFromEventStateManager();
75 bool IsManaging(nsPresContext
* aPresContext
, nsIContent
* aContent
);
76 bool IsEditorHandlingEventForComposition() const;
77 bool KeepAliveDuringDeactive() const
79 return mUpdatePreference
.WantDuringDeactive();
81 nsIWidget
* GetWidget() const { return mWidget
; }
82 nsresult
GetSelectionAndRoot(nsISelection
** aSelection
,
83 nsIContent
** aRoot
) const;
87 // mStartOffset is the start offset of modified or removed text in
88 // original content and inserted text in new content.
89 uint32_t mStartOffset
;
90 // mRemovalEndOffset is the end offset of modified or removed text in
91 // original content. If the value is same as mStartOffset, no text hasn't
93 uint32_t mRemovedEndOffset
;
94 // mAddedEndOffset is the end offset of inserted text or same as
95 // mStartOffset if just removed. The vlaue is offset in the new content.
96 uint32_t mAddedEndOffset
;
98 bool mCausedOnlyByComposition
;
103 , mRemovedEndOffset(0)
105 , mCausedOnlyByComposition(false)
110 TextChangeData(uint32_t aStartOffset
,
111 uint32_t aRemovedEndOffset
,
112 uint32_t aAddedEndOffset
,
113 bool aCausedByComposition
)
114 : mStartOffset(aStartOffset
)
115 , mRemovedEndOffset(aRemovedEndOffset
)
116 , mAddedEndOffset(aAddedEndOffset
)
117 , mCausedOnlyByComposition(aCausedByComposition
)
120 MOZ_ASSERT(aRemovedEndOffset
>= aStartOffset
,
121 "removed end offset must not be smaller than start offset");
122 MOZ_ASSERT(aAddedEndOffset
>= aStartOffset
,
123 "added end offset must not be smaller than start offset");
125 // Positive if text is added. Negative if text is removed.
126 int64_t Difference() const
128 return mAddedEndOffset
- mRemovedEndOffset
;
133 ~IMEContentObserver() {}
135 void MaybeNotifyIMEOfTextChange(const TextChangeData
& aTextChangeData
);
136 void MaybeNotifyIMEOfSelectionChange(bool aCausedByComposition
);
137 void MaybeNotifyIMEOfPositionChange();
139 void NotifyContentAdded(nsINode
* aContainer
, int32_t aStart
, int32_t aEnd
);
140 void ObserveEditableNode();
142 * UnregisterObservers() unresiters all listeners and observers.
143 * @param aPostEvent When true, DOM event will be posted to the thread.
144 * Otherwise, dispatched when safe.
146 void UnregisterObservers(bool aPostEvent
);
147 void StoreTextChangeData(const TextChangeData
& aTextChangeData
);
148 void FlushMergeableNotifications();
151 void TestMergingTextChangeData();
154 nsCOMPtr
<nsIWidget
> mWidget
;
155 nsCOMPtr
<nsISelection
> mSelection
;
156 nsCOMPtr
<nsIContent
> mRootContent
;
157 nsCOMPtr
<nsINode
> mEditableNode
;
158 nsCOMPtr
<nsIDocShell
> mDocShell
;
159 nsCOMPtr
<nsIEditor
> mEditor
;
162 * FlatTextCache stores flat text length from start of the content to
163 * mNodeOffset of mContainerNode.
167 // mContainerNode and mNodeOffset represent a point in DOM tree. E.g.,
168 // if mContainerNode is a div element, mNodeOffset is index of its child.
169 nsCOMPtr
<nsINode
> mContainerNode
;
171 // Length of flat text generated from contents between the start of content
172 // and a child node whose index is mNodeOffset of mContainerNode.
173 uint32_t mFlatTextLength
;
183 mContainerNode
= nullptr;
188 void Cache(nsINode
* aContainer
, int32_t aNodeOffset
,
189 uint32_t aFlatTextLength
)
191 MOZ_ASSERT(aContainer
, "aContainer must not be null");
193 aNodeOffset
<= static_cast<int32_t>(aContainer
->GetChildCount()),
194 "aNodeOffset must be same as or less than the count of children");
195 mContainerNode
= aContainer
;
196 mNodeOffset
= aNodeOffset
;
197 mFlatTextLength
= aFlatTextLength
;
200 bool Match(nsINode
* aContainer
, int32_t aNodeOffset
) const
202 return aContainer
== mContainerNode
&& aNodeOffset
== mNodeOffset
;
205 // mEndOfAddedTextCache caches text length from the start of content to
206 // the end of the last added content only while an edit action is being
207 // handled by the editor and no other mutation (e.g., removing node)
209 FlatTextCache mEndOfAddedTextCache
;
210 // mStartOfRemovingTextRangeCache caches text length from the start of content
211 // to the start of the last removed content only while an edit action is being
212 // handled by the editor and no other mutation (e.g., adding node) occur.
213 FlatTextCache mStartOfRemovingTextRangeCache
;
215 TextChangeData mTextChangeData
;
217 EventStateManager
* mESM
;
219 nsIMEUpdatePreference mUpdatePreference
;
220 uint32_t mPreAttrChangeLength
;
221 int64_t mPreCharacterDataChangeLength
;
223 bool mIsSelectionChangeEventPending
;
224 bool mSelectionChangeCausedOnlyByComposition
;
225 bool mIsPositionChangeEventPending
;
226 bool mIsFlushingPendingNotifications
;
229 } // namespace mozilla
231 #endif // mozilla_IMEContentObserver_h_