/work/obj-fuzz/dist/include/mozilla/TextComposition.h
Line | Count | Source (jump to first uncovered line) |
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_TextComposition_h |
8 | | #define mozilla_TextComposition_h |
9 | | |
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" |
20 | | #include "mozilla/dom/TabParent.h" |
21 | | #include "mozilla/dom/Text.h" |
22 | | |
23 | | namespace mozilla { |
24 | | |
25 | | class EditorBase; |
26 | | class EventDispatchingCallback; |
27 | | class IMEStateManager; |
28 | | |
29 | | /** |
30 | | * TextComposition represents a text composition. This class stores the |
31 | | * composition event target and its presContext. At dispatching the event via |
32 | | * this class, the instances use the stored event target. |
33 | | */ |
34 | | |
35 | | class TextComposition final |
36 | | { |
37 | | friend class IMEStateManager; |
38 | | |
39 | | NS_INLINE_DECL_REFCOUNTING(TextComposition) |
40 | | |
41 | | public: |
42 | | typedef dom::TabParent TabParent; |
43 | | typedef dom::Text Text; |
44 | | |
45 | 0 | static bool IsHandlingSelectionEvent() { return sHandlingSelectionEvent; } |
46 | | |
47 | | TextComposition(nsPresContext* aPresContext, |
48 | | nsINode* aNode, |
49 | | TabParent* aTabParent, |
50 | | WidgetCompositionEvent* aCompositionEvent); |
51 | | |
52 | 0 | bool Destroyed() const { return !mPresContext; } |
53 | 0 | nsPresContext* GetPresContext() const { return mPresContext; } |
54 | 0 | nsINode* GetEventTargetNode() const { return mNode; } |
55 | | // The text node which includes composition string. |
56 | 0 | Text* GetContainerTextNode() const { return mContainerTextNode; } |
57 | | // The latest CompositionEvent.data value except compositionstart event. |
58 | | // This value is modified at dispatching compositionupdate. |
59 | 0 | const nsString& LastData() const { return mLastData; } |
60 | | // The composition string which is already handled by the focused editor. |
61 | | // I.e., this value must be same as the composition string on the focused |
62 | | // editor. This value is modified at a call of |
63 | | // EditorDidHandleCompositionChangeEvent(). |
64 | | // Note that mString and mLastData are different between dispatcing |
65 | | // compositionupdate and compositionchange event handled by focused editor. |
66 | 0 | const nsString& String() const { return mString; } |
67 | | // The latest clauses range of the composition string. |
68 | | // During compositionupdate event, GetRanges() returns old ranges. |
69 | | // So if getting on compositionupdate, Use GetLastRange instead of GetRange(). |
70 | 0 | TextRangeArray* GetLastRanges() const { return mLastRanges; } |
71 | | // Returns the clauses and/or caret range of the composition string. |
72 | | // This is modified at a call of EditorWillHandleCompositionChangeEvent(). |
73 | | // This may return null if there is no clauses and caret. |
74 | | // XXX We should return |const TextRangeArray*| here, but it causes compile |
75 | | // error due to inaccessible Release() method. |
76 | 0 | TextRangeArray* GetRanges() const { return mRanges; } |
77 | | // Returns the widget which is proper to call NotifyIME(). |
78 | | nsIWidget* GetWidget() const |
79 | 0 | { |
80 | 0 | return mPresContext ? mPresContext->GetRootWidget() : nullptr; |
81 | 0 | } |
82 | | // Returns the tab parent which has this composition in its remote process. |
83 | | TabParent* GetTabParent() const |
84 | 0 | { |
85 | 0 | return mTabParent; |
86 | 0 | } |
87 | | // Returns true if the composition is started with synthesized event which |
88 | | // came from nsDOMWindowUtils. |
89 | 0 | bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; } |
90 | | |
91 | | const widget::NativeIMEContext& GetNativeIMEContext() const |
92 | 0 | { |
93 | 0 | return mNativeContext; |
94 | 0 | } |
95 | | |
96 | | /** |
97 | | * This is called when IMEStateManager stops managing the instance. |
98 | | */ |
99 | | void Destroy(); |
100 | | |
101 | | /** |
102 | | * Request to commit (or cancel) the composition to IME. This method should |
103 | | * be called only by IMEStateManager::NotifyIME(). |
104 | | */ |
105 | | nsresult RequestToCommit(nsIWidget* aWidget, bool aDiscard); |
106 | | |
107 | | /** |
108 | | * IsRequestingCommitOrCancelComposition() returns true if the instance is |
109 | | * requesting widget to commit or cancel composition. |
110 | | */ |
111 | | bool IsRequestingCommitOrCancelComposition() const |
112 | 0 | { |
113 | 0 | return mIsRequestingCancel || mIsRequestingCommit; |
114 | 0 | } |
115 | | |
116 | | /** |
117 | | * Send a notification to IME. It depends on the IME or platform spec what |
118 | | * will occur (or not occur). |
119 | | */ |
120 | | nsresult NotifyIME(widget::IMEMessage aMessage); |
121 | | |
122 | | /** |
123 | | * the offset of first composition string |
124 | | */ |
125 | | uint32_t NativeOffsetOfStartComposition() const |
126 | 0 | { |
127 | 0 | return mCompositionStartOffset; |
128 | 0 | } |
129 | | |
130 | | /** |
131 | | * the offset of first selected clause or start of composition |
132 | | */ |
133 | | uint32_t NativeOffsetOfTargetClause() const |
134 | 0 | { |
135 | 0 | return mCompositionStartOffset + mTargetClauseOffsetInComposition; |
136 | 0 | } |
137 | | |
138 | | /** |
139 | | * The offset of composition string in the text node. If composition string |
140 | | * hasn't been inserted in any text node yet, this returns UINT32_MAX. |
141 | | */ |
142 | | uint32_t XPOffsetInTextNode() const |
143 | 0 | { |
144 | 0 | return mCompositionStartOffsetInTextNode; |
145 | 0 | } |
146 | | |
147 | | /** |
148 | | * The length of composition string in the text node. If composition string |
149 | | * hasn't been inserted in any text node yet, this returns 0. |
150 | | */ |
151 | | uint32_t XPLengthInTextNode() const |
152 | 0 | { |
153 | 0 | return mCompositionLengthInTextNode == UINT32_MAX ? |
154 | 0 | 0 : mCompositionLengthInTextNode; |
155 | 0 | } |
156 | | |
157 | | /** |
158 | | * The end offset of composition string in the text node. If composition |
159 | | * string hasn't been inserted in any text node yet, this returns UINT32_MAX. |
160 | | */ |
161 | | uint32_t XPEndOffsetInTextNode() const |
162 | 0 | { |
163 | 0 | if (mCompositionStartOffsetInTextNode == UINT32_MAX || |
164 | 0 | mCompositionLengthInTextNode == UINT32_MAX) { |
165 | 0 | return UINT32_MAX; |
166 | 0 | } |
167 | 0 | return mCompositionStartOffsetInTextNode + mCompositionLengthInTextNode; |
168 | 0 | } |
169 | | |
170 | | /** |
171 | | * Returns true if there is non-empty composition string and it's not fixed. |
172 | | * Otherwise, false. |
173 | | */ |
174 | 0 | bool IsComposing() const { return mIsComposing; } |
175 | | |
176 | | /** |
177 | | * Returns true while editor is handling an event which is modifying the |
178 | | * composition string. |
179 | | */ |
180 | | bool IsEditorHandlingEvent() const |
181 | 0 | { |
182 | 0 | return mIsEditorHandlingEvent; |
183 | 0 | } |
184 | | |
185 | | /** |
186 | | * IsMovingToNewTextNode() returns true if editor detects the text node |
187 | | * has been removed and still not insert the composition string into |
188 | | * new text node. |
189 | | */ |
190 | | bool IsMovingToNewTextNode() const |
191 | 0 | { |
192 | 0 | return !mContainerTextNode && mCompositionLengthInTextNode && |
193 | 0 | mCompositionLengthInTextNode != UINT32_MAX; |
194 | 0 | } |
195 | | |
196 | | /** |
197 | | * StartHandlingComposition() and EndHandlingComposition() are called by |
198 | | * editor when it holds a TextComposition instance and release it. |
199 | | */ |
200 | | void StartHandlingComposition(EditorBase* aEditorBase); |
201 | | void EndHandlingComposition(EditorBase* aEditorBase); |
202 | | |
203 | | /** |
204 | | * OnEditorDestroyed() is called when the editor is destroyed but there is |
205 | | * active composition. |
206 | | */ |
207 | | void OnEditorDestroyed(); |
208 | | |
209 | | /** |
210 | | * CompositionChangeEventHandlingMarker class should be created at starting |
211 | | * to handle text event in focused editor. This calls |
212 | | * EditorWillHandleCompositionChangeEvent() and |
213 | | * EditorDidHandleCompositionChangeEvent() automatically. |
214 | | */ |
215 | | class MOZ_STACK_CLASS CompositionChangeEventHandlingMarker |
216 | | { |
217 | | public: |
218 | | CompositionChangeEventHandlingMarker( |
219 | | TextComposition* aComposition, |
220 | | const WidgetCompositionEvent* aCompositionChangeEvent) |
221 | | : mComposition(aComposition) |
222 | 0 | { |
223 | 0 | mComposition->EditorWillHandleCompositionChangeEvent( |
224 | 0 | aCompositionChangeEvent); |
225 | 0 | } |
226 | | |
227 | | ~CompositionChangeEventHandlingMarker() |
228 | 0 | { |
229 | 0 | mComposition->EditorDidHandleCompositionChangeEvent(); |
230 | 0 | } |
231 | | |
232 | | private: |
233 | | RefPtr<TextComposition> mComposition; |
234 | | CompositionChangeEventHandlingMarker(); |
235 | | CompositionChangeEventHandlingMarker( |
236 | | const CompositionChangeEventHandlingMarker& aOther); |
237 | | }; |
238 | | |
239 | | /** |
240 | | * OnCreateCompositionTransaction() is called by |
241 | | * CompositionTransaction::Create() immediately after creating |
242 | | * new CompositionTransaction instance. |
243 | | * |
244 | | * @param aStringToInsert The string to insert the text node actually. |
245 | | * This may be different from the data of |
246 | | * dispatching composition event because it may |
247 | | * be replaced with different character for |
248 | | * passwords, or truncated due to maxlength. |
249 | | * @param aTextNode The text node which includes composition string. |
250 | | * @param aOffset The offset of composition string in aTextNode. |
251 | | */ |
252 | | void OnCreateCompositionTransaction(const nsAString& aStringToInsert, |
253 | | Text* aTextNode, |
254 | | uint32_t aOffset) |
255 | 0 | { |
256 | 0 | if (!mContainerTextNode) { |
257 | 0 | mContainerTextNode = aTextNode; |
258 | 0 | mCompositionStartOffsetInTextNode = aOffset; |
259 | 0 | NS_WARNING_ASSERTION(mCompositionStartOffsetInTextNode != UINT32_MAX, |
260 | 0 | "The text node is really too long."); |
261 | 0 | } |
262 | | #ifdef DEBUG |
263 | | else { |
264 | | MOZ_ASSERT(aTextNode == mContainerTextNode); |
265 | | MOZ_ASSERT(aOffset == mCompositionStartOffsetInTextNode); |
266 | | } |
267 | | #endif // #ifdef DEBUG |
268 | | mCompositionLengthInTextNode = aStringToInsert.Length(); |
269 | 0 | NS_WARNING_ASSERTION(mCompositionLengthInTextNode != UINT32_MAX, |
270 | 0 | "The string to insert is really too long."); |
271 | 0 | } |
272 | | |
273 | | /** |
274 | | * OnTextNodeRemoved() is called when focused editor is reframed and |
275 | | * mContainerTextNode may be (or have been) replaced with different text |
276 | | * node, or just removes the text node due to empty. |
277 | | */ |
278 | | void OnTextNodeRemoved() |
279 | 0 | { |
280 | 0 | mContainerTextNode = nullptr; |
281 | 0 | // Don't reset mCompositionStartOffsetInTextNode nor |
282 | 0 | // mCompositionLengthInTextNode because editor needs them to restore |
283 | 0 | // composition in new text node. |
284 | 0 | } |
285 | | |
286 | | private: |
287 | | // Private destructor, to discourage deletion outside of Release(): |
288 | | ~TextComposition() |
289 | 0 | { |
290 | 0 | // WARNING: mPresContext may be destroying, so, be careful if you touch it. |
291 | 0 | } |
292 | | |
293 | | // sHandlingSelectionEvent is true while TextComposition sends a selection |
294 | | // event to ContentEventHandler. |
295 | | static bool sHandlingSelectionEvent; |
296 | | |
297 | | // This class holds nsPresContext weak. This instance shouldn't block |
298 | | // destroying it. When the presContext is being destroyed, it's notified to |
299 | | // IMEStateManager::OnDestroyPresContext(), and then, it destroy |
300 | | // this instance. |
301 | | nsPresContext* mPresContext; |
302 | | nsCOMPtr<nsINode> mNode; |
303 | | RefPtr<TabParent> mTabParent; |
304 | | |
305 | | // The text node which includes the composition string. |
306 | | RefPtr<Text> mContainerTextNode; |
307 | | |
308 | | // This is the clause and caret range information which is managed by |
309 | | // the focused editor. This may be null if there is no clauses or caret. |
310 | | RefPtr<TextRangeArray> mRanges; |
311 | | // Same as mRange, but mRange will have old data during compositionupdate. |
312 | | // So this will be valied during compositionupdate. |
313 | | RefPtr<TextRangeArray> mLastRanges; |
314 | | |
315 | | // mNativeContext stores a opaque pointer. This works as the "ID" for this |
316 | | // composition. Don't access the instance, it may not be available. |
317 | | widget::NativeIMEContext mNativeContext; |
318 | | |
319 | | // mEditorBaseWeak is a weak reference to the focused editor handling |
320 | | // composition. |
321 | | nsWeakPtr mEditorBaseWeak; |
322 | | |
323 | | // mLastData stores the data attribute of the latest composition event (except |
324 | | // the compositionstart event). |
325 | | nsString mLastData; |
326 | | |
327 | | // mString stores the composition text which has been handled by the focused |
328 | | // editor. |
329 | | nsString mString; |
330 | | |
331 | | // Offset of the composition string from start of the editor |
332 | | uint32_t mCompositionStartOffset; |
333 | | // Offset of the selected clause of the composition string from |
334 | | // mCompositionStartOffset |
335 | | uint32_t mTargetClauseOffsetInComposition; |
336 | | // Offset of the composition string in mContainerTextNode. |
337 | | // NOTE: This is NOT valid in the main process if focused editor is in a |
338 | | // remote process. |
339 | | uint32_t mCompositionStartOffsetInTextNode; |
340 | | // Length of the composition string in mContainerTextNode. If this instance |
341 | | // has already dispatched eCompositionCommit(AsIs) and |
342 | | // EditorDidHandleCompositionChangeEvent() has already been called, |
343 | | // this may be different from length of mString because committed string |
344 | | // may be truncated by maxlength attribute of <input> or <textarea>. |
345 | | // NOTE: This is NOT valid in the main process if focused editor is in a |
346 | | // remote process. |
347 | | uint32_t mCompositionLengthInTextNode; |
348 | | |
349 | | // See the comment for IsSynthesizedForTests(). |
350 | | bool mIsSynthesizedForTests; |
351 | | |
352 | | // See the comment for IsComposing(). |
353 | | bool mIsComposing; |
354 | | |
355 | | // mIsEditorHandlingEvent is true while editor is modifying the composition |
356 | | // string. |
357 | | bool mIsEditorHandlingEvent; |
358 | | |
359 | | // mIsRequestingCommit or mIsRequestingCancel is true *only* while we're |
360 | | // requesting commit or canceling the composition. In other words, while |
361 | | // one of these values is true, we're handling the request. |
362 | | bool mIsRequestingCommit; |
363 | | bool mIsRequestingCancel; |
364 | | |
365 | | // mRequestedToCommitOrCancel is true *after* we requested IME to commit or |
366 | | // cancel the composition. In other words, we already requested of IME that |
367 | | // it commits or cancels current composition. |
368 | | // NOTE: Before this is set to true, both mIsRequestingCommit and |
369 | | // mIsRequestingCancel are set to false. |
370 | | bool mRequestedToCommitOrCancel; |
371 | | |
372 | | // Set to true if the instance dispatches an eCompositionChange event. |
373 | | bool mHasDispatchedDOMTextEvent; |
374 | | |
375 | | // Before this dispatches commit event into the tree, this is set to true. |
376 | | // So, this means if native IME already commits the composition. |
377 | | bool mHasReceivedCommitEvent; |
378 | | |
379 | | // mWasNativeCompositionEndEventDiscarded is true if this composition was |
380 | | // requested commit or cancel itself but native compositionend event is |
381 | | // discarded by PresShell due to not safe to dispatch events. |
382 | | bool mWasNativeCompositionEndEventDiscarded; |
383 | | |
384 | | // Allow control characters appear in composition string. |
385 | | // When this is false, control characters except |
386 | | // CHARACTER TABULATION (horizontal tab) are removed from |
387 | | // both composition string and data attribute of compositionupdate |
388 | | // and compositionend events. |
389 | | bool mAllowControlCharacters; |
390 | | |
391 | | // mWasCompositionStringEmpty is true if the composition string was empty |
392 | | // when DispatchCompositionEvent() is called. |
393 | | bool mWasCompositionStringEmpty; |
394 | | |
395 | | // Hide the default constructor and copy constructor. |
396 | | TextComposition() |
397 | | : mPresContext(nullptr) |
398 | | , mNativeContext(nullptr) |
399 | | , mCompositionStartOffset(0) |
400 | | , mTargetClauseOffsetInComposition(0) |
401 | | , mCompositionStartOffsetInTextNode(UINT32_MAX) |
402 | | , mCompositionLengthInTextNode(UINT32_MAX) |
403 | | , mIsSynthesizedForTests(false) |
404 | | , mIsComposing(false) |
405 | | , mIsEditorHandlingEvent(false) |
406 | | , mIsRequestingCommit(false) |
407 | | , mIsRequestingCancel(false) |
408 | | , mRequestedToCommitOrCancel(false) |
409 | | , mHasReceivedCommitEvent(false) |
410 | | , mWasNativeCompositionEndEventDiscarded(false) |
411 | | , mAllowControlCharacters(false) |
412 | | , mWasCompositionStringEmpty(true) |
413 | 0 | {} |
414 | | TextComposition(const TextComposition& aOther); |
415 | | |
416 | | /** |
417 | | * If we're requesting IME to commit or cancel composition, or we've already |
418 | | * requested it, or we've already known this composition has been ended in |
419 | | * IME, we don't need to request commit nor cancel composition anymore and |
420 | | * shouldn't do so if we're in content process for not committing/canceling |
421 | | * "current" composition in native IME. So, when this returns true, |
422 | | * RequestIMEToCommit() does nothing. |
423 | | */ |
424 | | bool CanRequsetIMEToCommitOrCancelComposition() const |
425 | 0 | { |
426 | 0 | return !mIsRequestingCommit && !mIsRequestingCancel && |
427 | 0 | !mRequestedToCommitOrCancel && !mHasReceivedCommitEvent; |
428 | 0 | } |
429 | | |
430 | | /** |
431 | | * GetEditorBase() returns EditorBase pointer of mEditorBaseWeak. |
432 | | */ |
433 | | already_AddRefed<EditorBase> GetEditorBase() const; |
434 | | |
435 | | /** |
436 | | * HasEditor() returns true if mEditorBaseWeak holds EditorBase instance |
437 | | * which is alive. Otherwise, false. |
438 | | */ |
439 | | bool HasEditor() const; |
440 | | |
441 | | /** |
442 | | * EditorWillHandleCompositionChangeEvent() must be called before the focused |
443 | | * editor handles the compositionchange event. |
444 | | */ |
445 | | void EditorWillHandleCompositionChangeEvent( |
446 | | const WidgetCompositionEvent* aCompositionChangeEvent); |
447 | | |
448 | | /** |
449 | | * EditorDidHandleCompositionChangeEvent() must be called after the focused |
450 | | * editor handles a compositionchange event. |
451 | | */ |
452 | | void EditorDidHandleCompositionChangeEvent(); |
453 | | |
454 | | /** |
455 | | * IsValidStateForComposition() returns true if it's safe to dispatch an event |
456 | | * to the DOM tree. Otherwise, false. |
457 | | * WARNING: This doesn't check script blocker state. It should be checked |
458 | | * before dispatching the first event. |
459 | | */ |
460 | | bool IsValidStateForComposition(nsIWidget* aWidget) const; |
461 | | |
462 | | /** |
463 | | * DispatchCompositionEvent() dispatches the aCompositionEvent to the mContent |
464 | | * synchronously. The caller must ensure that it's safe to dispatch the event. |
465 | | */ |
466 | | void DispatchCompositionEvent(WidgetCompositionEvent* aCompositionEvent, |
467 | | nsEventStatus* aStatus, |
468 | | EventDispatchingCallback* aCallBack, |
469 | | bool aIsSynthesized); |
470 | | |
471 | | /** |
472 | | * Simply calling EventDispatcher::Dispatch() with plugin event. |
473 | | * If dispatching event has no orginal clone, aOriginalEvent can be null. |
474 | | */ |
475 | | void DispatchEvent(WidgetCompositionEvent* aDispatchEvent, |
476 | | nsEventStatus* aStatus, |
477 | | EventDispatchingCallback* aCallback, |
478 | | const WidgetCompositionEvent *aOriginalEvent = nullptr); |
479 | | |
480 | | /** |
481 | | * HandleSelectionEvent() sends the selection event to ContentEventHandler |
482 | | * or dispatches it to the focused child process. |
483 | | */ |
484 | | void HandleSelectionEvent(WidgetSelectionEvent* aSelectionEvent) |
485 | 0 | { |
486 | 0 | HandleSelectionEvent(mPresContext, mTabParent, aSelectionEvent); |
487 | 0 | } |
488 | | static void HandleSelectionEvent(nsPresContext* aPresContext, |
489 | | TabParent* aTabParent, |
490 | | WidgetSelectionEvent* aSelectionEvent); |
491 | | |
492 | | /** |
493 | | * MaybeDispatchCompositionUpdate() may dispatch a compositionupdate event |
494 | | * if aCompositionEvent changes composition string. |
495 | | * @return Returns false if dispatching the compositionupdate event caused |
496 | | * destroying this composition. |
497 | | */ |
498 | | bool MaybeDispatchCompositionUpdate( |
499 | | const WidgetCompositionEvent* aCompositionEvent); |
500 | | |
501 | | /** |
502 | | * CloneAndDispatchAs() dispatches a composition event which is |
503 | | * duplicateed from aCompositionEvent and set the aMessage. |
504 | | * |
505 | | * @return Returns BaseEventFlags which is the result of dispatched event. |
506 | | */ |
507 | | BaseEventFlags CloneAndDispatchAs( |
508 | | const WidgetCompositionEvent* aCompositionEvent, |
509 | | EventMessage aMessage, |
510 | | nsEventStatus* aStatus = nullptr, |
511 | | EventDispatchingCallback* aCallBack = nullptr); |
512 | | |
513 | | /** |
514 | | * If IME has already dispatched compositionend event but it was discarded |
515 | | * by PresShell due to not safe to dispatch, this returns true. |
516 | | */ |
517 | | bool WasNativeCompositionEndEventDiscarded() const |
518 | 0 | { |
519 | 0 | return mWasNativeCompositionEndEventDiscarded; |
520 | 0 | } |
521 | | |
522 | | /** |
523 | | * OnCompositionEventDiscarded() is called when PresShell discards |
524 | | * compositionupdate, compositionend or compositionchange event due to not |
525 | | * safe to dispatch event. |
526 | | */ |
527 | | void OnCompositionEventDiscarded(WidgetCompositionEvent* aCompositionEvent); |
528 | | |
529 | | /** |
530 | | * OnCompositionEventDispatched() is called after a composition event is |
531 | | * dispatched. |
532 | | */ |
533 | | void OnCompositionEventDispatched( |
534 | | const WidgetCompositionEvent* aDispatchEvent); |
535 | | |
536 | | /** |
537 | | * MaybeNotifyIMEOfCompositionEventHandled() notifies IME of composition |
538 | | * event handled. This should be called after dispatching a composition |
539 | | * event which came from widget. |
540 | | */ |
541 | | void MaybeNotifyIMEOfCompositionEventHandled( |
542 | | const WidgetCompositionEvent* aCompositionEvent); |
543 | | |
544 | | /** |
545 | | * GetSelectionStartOffset() returns normal selection start offset in the |
546 | | * editor which has this composition. |
547 | | * If it failed or lost focus, this would return 0. |
548 | | */ |
549 | | uint32_t GetSelectionStartOffset(); |
550 | | |
551 | | /** |
552 | | * OnStartOffsetUpdatedInChild() is called when composition start offset |
553 | | * is updated in the child process. I.e., this is called and never called |
554 | | * if the composition is in this process. |
555 | | * @param aStartOffset New composition start offset with native |
556 | | * linebreaks. |
557 | | */ |
558 | | void OnStartOffsetUpdatedInChild(uint32_t aStartOffset); |
559 | | |
560 | | /** |
561 | | * CompositionEventDispatcher dispatches the specified composition (or text) |
562 | | * event. |
563 | | */ |
564 | | class CompositionEventDispatcher : public Runnable |
565 | | { |
566 | | public: |
567 | | CompositionEventDispatcher(TextComposition* aTextComposition, |
568 | | nsINode* aEventTarget, |
569 | | EventMessage aEventMessage, |
570 | | const nsAString& aData, |
571 | | bool aIsSynthesizedEvent = false); |
572 | | NS_IMETHOD Run() override; |
573 | | |
574 | | private: |
575 | | RefPtr<TextComposition> mTextComposition; |
576 | | nsCOMPtr<nsINode> mEventTarget; |
577 | | nsString mData; |
578 | | EventMessage mEventMessage; |
579 | | bool mIsSynthesizedEvent; |
580 | | |
581 | | CompositionEventDispatcher() |
582 | | : Runnable("TextComposition::CompositionEventDispatcher") |
583 | | , mEventMessage(eVoidEvent) |
584 | 0 | , mIsSynthesizedEvent(false){}; |
585 | | }; |
586 | | |
587 | | /** |
588 | | * DispatchCompositionEventRunnable() dispatches a composition event to the |
589 | | * content. Be aware, if you use this method, nsPresShellEventCB isn't used. |
590 | | * That means that nsIFrame::HandleEvent() is never called. |
591 | | * WARNING: The instance which is managed by IMEStateManager may be |
592 | | * destroyed by this method call. |
593 | | * |
594 | | * @param aEventMessage Must be one of composition events. |
595 | | * @param aData Used for mData value. |
596 | | * @param aIsSynthesizingCommit true if this is called for synthesizing |
597 | | * commit or cancel composition. Otherwise, |
598 | | * false. |
599 | | */ |
600 | | void DispatchCompositionEventRunnable(EventMessage aEventMessage, |
601 | | const nsAString& aData, |
602 | | bool aIsSynthesizingCommit = false); |
603 | | }; |
604 | | |
605 | | /** |
606 | | * TextCompositionArray manages the instances of TextComposition class. |
607 | | * Managing with array is enough because only one composition is typically |
608 | | * there. Even if user switches native IME context, it's very rare that |
609 | | * second or more composition is started. |
610 | | * It's assumed that this is used by IMEStateManager for storing all active |
611 | | * compositions in the process. If the instance is it, each TextComposition |
612 | | * in the array can be destroyed by calling some methods of itself. |
613 | | */ |
614 | | |
615 | | class TextCompositionArray final : |
616 | | public AutoTArray<RefPtr<TextComposition>, 2> |
617 | | { |
618 | | public: |
619 | | // Looking for per native IME context. |
620 | | index_type IndexOf(const widget::NativeIMEContext& aNativeIMEContext); |
621 | | index_type IndexOf(nsIWidget* aWidget); |
622 | | |
623 | | TextComposition* GetCompositionFor(nsIWidget* aWidget); |
624 | | TextComposition* GetCompositionFor( |
625 | | const WidgetCompositionEvent* aCompositionEvent); |
626 | | |
627 | | // Looking for per nsPresContext |
628 | | index_type IndexOf(nsPresContext* aPresContext); |
629 | | index_type IndexOf(nsPresContext* aPresContext, nsINode* aNode); |
630 | | |
631 | | TextComposition* GetCompositionFor(nsPresContext* aPresContext); |
632 | | TextComposition* GetCompositionFor(nsPresContext* aPresContext, |
633 | | nsINode* aNode); |
634 | | TextComposition* GetCompositionInContent(nsPresContext* aPresContext, |
635 | | nsIContent* aContent); |
636 | | }; |
637 | | |
638 | | } // namespace mozilla |
639 | | |
640 | | #endif // #ifndef mozilla_TextComposition_h |