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