IMEContentObserver.cpp 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/Logging.h"
  6. #include "ContentEventHandler.h"
  7. #include "IMEContentObserver.h"
  8. #include "mozilla/AsyncEventDispatcher.h"
  9. #include "mozilla/AutoRestore.h"
  10. #include "mozilla/EventStateManager.h"
  11. #include "mozilla/IMEStateManager.h"
  12. #include "mozilla/MouseEvents.h"
  13. #include "mozilla/TextComposition.h"
  14. #include "mozilla/TextEvents.h"
  15. #include "mozilla/dom/Element.h"
  16. #include "nsContentUtils.h"
  17. #include "nsGkAtoms.h"
  18. #include "nsIAtom.h"
  19. #include "nsIContent.h"
  20. #include "nsIDocument.h"
  21. #include "nsIDOMDocument.h"
  22. #include "nsIDOMRange.h"
  23. #include "nsIEditorIMESupport.h"
  24. #include "nsIFrame.h"
  25. #include "nsINode.h"
  26. #include "nsIPresShell.h"
  27. #include "nsISelectionController.h"
  28. #include "nsISelectionPrivate.h"
  29. #include "nsISupports.h"
  30. #include "nsIWidget.h"
  31. #include "nsPresContext.h"
  32. #include "nsWeakReference.h"
  33. #include "WritingModes.h"
  34. namespace mozilla {
  35. using namespace widget;
  36. LazyLogModule sIMECOLog("IMEContentObserver");
  37. static const char*
  38. ToChar(bool aBool)
  39. {
  40. return aBool ? "true" : "false";
  41. }
  42. class WritingModeToString final : public nsAutoCString
  43. {
  44. public:
  45. explicit WritingModeToString(const WritingMode& aWritingMode)
  46. {
  47. if (!aWritingMode.IsVertical()) {
  48. AssignLiteral("Horizontal");
  49. return;
  50. }
  51. if (aWritingMode.IsVerticalLR()) {
  52. AssignLiteral("Vertical (LR)");
  53. return;
  54. }
  55. AssignLiteral("Vertical (RL)");
  56. }
  57. virtual ~WritingModeToString() {}
  58. };
  59. class SelectionChangeDataToString final : public nsAutoCString
  60. {
  61. public:
  62. explicit SelectionChangeDataToString(
  63. const IMENotification::SelectionChangeDataBase& aData)
  64. {
  65. if (!aData.IsValid()) {
  66. AppendLiteral("{ IsValid()=false }");
  67. return;
  68. }
  69. AppendPrintf("{ mOffset=%u, ", aData.mOffset);
  70. if (aData.mString->Length() > 20) {
  71. AppendPrintf("mString.Length()=%u, ", aData.mString->Length());
  72. } else {
  73. AppendPrintf("mString=\"%s\" (Length()=%u), ",
  74. NS_ConvertUTF16toUTF8(*aData.mString).get(),
  75. aData.mString->Length());
  76. }
  77. AppendPrintf("GetWritingMode()=%s, mReversed=%s, mCausedByComposition=%s, "
  78. "mCausedBySelectionEvent=%s }",
  79. WritingModeToString(aData.GetWritingMode()).get(),
  80. ToChar(aData.mReversed),
  81. ToChar(aData.mCausedByComposition),
  82. ToChar(aData.mCausedBySelectionEvent));
  83. }
  84. virtual ~SelectionChangeDataToString() {}
  85. };
  86. class TextChangeDataToString final : public nsAutoCString
  87. {
  88. public:
  89. explicit TextChangeDataToString(
  90. const IMENotification::TextChangeDataBase& aData)
  91. {
  92. if (!aData.IsValid()) {
  93. AppendLiteral("{ IsValid()=false }");
  94. return;
  95. }
  96. AppendPrintf("{ mStartOffset=%u, mRemovedEndOffset=%u, mAddedEndOffset=%u, "
  97. "mCausedOnlyByComposition=%s, "
  98. "mIncludingChangesDuringComposition=%s, "
  99. "mIncludingChangesWithoutComposition=%s }",
  100. aData.mStartOffset, aData.mRemovedEndOffset,
  101. aData.mAddedEndOffset,
  102. ToChar(aData.mCausedOnlyByComposition),
  103. ToChar(aData.mIncludingChangesDuringComposition),
  104. ToChar(aData.mIncludingChangesWithoutComposition));
  105. }
  106. virtual ~TextChangeDataToString() {}
  107. };
  108. /******************************************************************************
  109. * mozilla::IMEContentObserver
  110. ******************************************************************************/
  111. NS_IMPL_CYCLE_COLLECTION_CLASS(IMEContentObserver)
  112. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IMEContentObserver)
  113. nsAutoScriptBlocker scriptBlocker;
  114. tmp->NotifyIMEOfBlur();
  115. tmp->UnregisterObservers();
  116. NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelection)
  117. NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootContent)
  118. NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditableNode)
  119. NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
  120. NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditor)
  121. NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndOfAddedTextCache.mContainerNode)
  122. NS_IMPL_CYCLE_COLLECTION_UNLINK(mStartOfRemovingTextRangeCache.mContainerNode)
  123. tmp->mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
  124. tmp->mESM = nullptr;
  125. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  126. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IMEContentObserver)
  127. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWidget)
  128. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedWidget)
  129. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelection)
  130. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootContent)
  131. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditableNode)
  132. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
  133. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditor)
  134. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndOfAddedTextCache.mContainerNode)
  135. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
  136. mStartOfRemovingTextRangeCache.mContainerNode)
  137. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  138. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IMEContentObserver)
  139. NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
  140. NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
  141. NS_INTERFACE_MAP_ENTRY(nsIReflowObserver)
  142. NS_INTERFACE_MAP_ENTRY(nsIScrollObserver)
  143. NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
  144. NS_INTERFACE_MAP_ENTRY(nsIEditorObserver)
  145. NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISelectionListener)
  146. NS_INTERFACE_MAP_END
  147. NS_IMPL_CYCLE_COLLECTING_ADDREF(IMEContentObserver)
  148. NS_IMPL_CYCLE_COLLECTING_RELEASE(IMEContentObserver)
  149. IMEContentObserver::IMEContentObserver()
  150. : mESM(nullptr)
  151. , mSuppressNotifications(0)
  152. , mPreCharacterDataChangeLength(-1)
  153. , mSendingNotification(NOTIFY_IME_OF_NOTHING)
  154. , mIsObserving(false)
  155. , mIMEHasFocus(false)
  156. , mNeedsToNotifyIMEOfFocusSet(false)
  157. , mNeedsToNotifyIMEOfTextChange(false)
  158. , mNeedsToNotifyIMEOfSelectionChange(false)
  159. , mNeedsToNotifyIMEOfPositionChange(false)
  160. , mNeedsToNotifyIMEOfCompositionEventHandled(false)
  161. , mIsHandlingQueryContentEvent(false)
  162. {
  163. #ifdef DEBUG
  164. mTextChangeData.Test();
  165. #endif
  166. }
  167. void
  168. IMEContentObserver::Init(nsIWidget* aWidget,
  169. nsPresContext* aPresContext,
  170. nsIContent* aContent,
  171. nsIEditor* aEditor)
  172. {
  173. State state = GetState();
  174. if (NS_WARN_IF(state == eState_Observing)) {
  175. return; // Nothing to do.
  176. }
  177. bool firstInitialization = state != eState_StoppedObserving;
  178. if (!firstInitialization) {
  179. // If this is now trying to initialize with new contents, all observers
  180. // should be registered again for simpler implementation.
  181. UnregisterObservers();
  182. // Clear members which may not be initialized again.
  183. Clear();
  184. }
  185. mESM = aPresContext->EventStateManager();
  186. mESM->OnStartToObserveContent(this);
  187. mWidget = aWidget;
  188. if (aWidget->GetInputContext().mIMEState.mEnabled == IMEState::PLUGIN) {
  189. if (!InitWithPlugin(aPresContext, aContent)) {
  190. Clear();
  191. return;
  192. }
  193. } else {
  194. if (!InitWithEditor(aPresContext, aContent, aEditor)) {
  195. Clear();
  196. return;
  197. }
  198. }
  199. if (firstInitialization) {
  200. // Now, try to send NOTIFY_IME_OF_FOCUS to IME via the widget.
  201. MaybeNotifyIMEOfFocusSet();
  202. // When this is called first time, IME has not received NOTIFY_IME_OF_FOCUS
  203. // yet since NOTIFY_IME_OF_FOCUS will be sent to widget asynchronously.
  204. // So, we need to do nothing here. After NOTIFY_IME_OF_FOCUS has been
  205. // sent, OnIMEReceivedFocus() will be called and content, selection and/or
  206. // position changes will be observed
  207. return;
  208. }
  209. // When this is called after editor reframing (i.e., the root editable node
  210. // is also recreated), IME has usually received NOTIFY_IME_OF_FOCUS. In this
  211. // case, we need to restart to observe content, selection and/or position
  212. // changes in new root editable node.
  213. ObserveEditableNode();
  214. if (!NeedsToNotifyIMEOfSomething()) {
  215. return;
  216. }
  217. // Some change events may wait to notify IME because this was being
  218. // initialized. It is the time to flush them.
  219. FlushMergeableNotifications();
  220. }
  221. void
  222. IMEContentObserver::OnIMEReceivedFocus()
  223. {
  224. // While Init() notifies IME of focus, pending layout may be flushed
  225. // because the notification may cause querying content. Then, recursive
  226. // call of Init() with the latest content may occur. In such case, we
  227. // shouldn't keep first initialization which notified IME of focus.
  228. if (GetState() != eState_Initializing) {
  229. return;
  230. }
  231. // NOTIFY_IME_OF_FOCUS might cause recreating IMEContentObserver
  232. // instance via IMEStateManager::UpdateIMEState(). So, this
  233. // instance might already have been destroyed, check it.
  234. if (!mRootContent) {
  235. return;
  236. }
  237. // Start to observe which is needed by IME when IME actually has focus.
  238. ObserveEditableNode();
  239. if (!NeedsToNotifyIMEOfSomething()) {
  240. return;
  241. }
  242. // Some change events may wait to notify IME because this was being
  243. // initialized. It is the time to flush them.
  244. FlushMergeableNotifications();
  245. }
  246. bool
  247. IMEContentObserver::InitWithEditor(nsPresContext* aPresContext,
  248. nsIContent* aContent,
  249. nsIEditor* aEditor)
  250. {
  251. MOZ_ASSERT(aEditor);
  252. mEditableNode =
  253. IMEStateManager::GetRootEditableNode(aPresContext, aContent);
  254. if (NS_WARN_IF(!mEditableNode)) {
  255. return false;
  256. }
  257. mEditor = aEditor;
  258. if (NS_WARN_IF(!mEditor)) {
  259. return false;
  260. }
  261. nsIPresShell* presShell = aPresContext->PresShell();
  262. // get selection and root content
  263. nsCOMPtr<nsISelectionController> selCon;
  264. if (mEditableNode->IsNodeOfType(nsINode::eCONTENT)) {
  265. nsIFrame* frame =
  266. static_cast<nsIContent*>(mEditableNode.get())->GetPrimaryFrame();
  267. if (NS_WARN_IF(!frame)) {
  268. return false;
  269. }
  270. frame->GetSelectionController(aPresContext,
  271. getter_AddRefs(selCon));
  272. } else {
  273. // mEditableNode is a document
  274. selCon = do_QueryInterface(presShell);
  275. }
  276. if (NS_WARN_IF(!selCon)) {
  277. return false;
  278. }
  279. selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
  280. getter_AddRefs(mSelection));
  281. if (NS_WARN_IF(!mSelection)) {
  282. return false;
  283. }
  284. nsCOMPtr<nsIDOMRange> selDomRange;
  285. if (NS_SUCCEEDED(mSelection->GetRangeAt(0, getter_AddRefs(selDomRange)))) {
  286. nsRange* selRange = static_cast<nsRange*>(selDomRange.get());
  287. if (NS_WARN_IF(!selRange) || NS_WARN_IF(!selRange->GetStartParent())) {
  288. return false;
  289. }
  290. mRootContent = selRange->GetStartParent()->
  291. GetSelectionRootContent(presShell);
  292. } else {
  293. mRootContent = mEditableNode->GetSelectionRootContent(presShell);
  294. }
  295. if (!mRootContent && mEditableNode->IsNodeOfType(nsINode::eDOCUMENT)) {
  296. // The document node is editable, but there are no contents, this document
  297. // is not editable.
  298. return false;
  299. }
  300. if (NS_WARN_IF(!mRootContent)) {
  301. return false;
  302. }
  303. mDocShell = aPresContext->GetDocShell();
  304. if (NS_WARN_IF(!mDocShell)) {
  305. return false;
  306. }
  307. MOZ_ASSERT(!WasInitializedWithPlugin());
  308. return true;
  309. }
  310. bool
  311. IMEContentObserver::InitWithPlugin(nsPresContext* aPresContext,
  312. nsIContent* aContent)
  313. {
  314. if (NS_WARN_IF(!aContent) ||
  315. NS_WARN_IF(aContent->GetDesiredIMEState().mEnabled != IMEState::PLUGIN)) {
  316. return false;
  317. }
  318. nsIFrame* frame = aContent->GetPrimaryFrame();
  319. if (NS_WARN_IF(!frame)) {
  320. return false;
  321. }
  322. nsCOMPtr<nsISelectionController> selCon;
  323. frame->GetSelectionController(aPresContext, getter_AddRefs(selCon));
  324. if (NS_WARN_IF(!selCon)) {
  325. return false;
  326. }
  327. selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
  328. getter_AddRefs(mSelection));
  329. if (NS_WARN_IF(!mSelection)) {
  330. return false;
  331. }
  332. mEditor = nullptr;
  333. mEditableNode = aContent;
  334. mRootContent = aContent;
  335. mDocShell = aPresContext->GetDocShell();
  336. if (NS_WARN_IF(!mDocShell)) {
  337. return false;
  338. }
  339. MOZ_ASSERT(WasInitializedWithPlugin());
  340. return true;
  341. }
  342. bool
  343. IMEContentObserver::WasInitializedWithPlugin() const
  344. {
  345. return mDocShell && !mEditor;
  346. }
  347. void
  348. IMEContentObserver::Clear()
  349. {
  350. mEditor = nullptr;
  351. mSelection = nullptr;
  352. mEditableNode = nullptr;
  353. mRootContent = nullptr;
  354. mDocShell = nullptr;
  355. }
  356. void
  357. IMEContentObserver::ObserveEditableNode()
  358. {
  359. MOZ_RELEASE_ASSERT(mSelection);
  360. MOZ_RELEASE_ASSERT(mRootContent);
  361. MOZ_RELEASE_ASSERT(GetState() != eState_Observing);
  362. // If this is called before sending NOTIFY_IME_OF_FOCUS (it's possible when
  363. // the editor is reframed before sending NOTIFY_IME_OF_FOCUS asynchronously),
  364. // the update preference of mWidget may be different from after the widget
  365. // receives NOTIFY_IME_OF_FOCUS. So, this should be called again by
  366. // OnIMEReceivedFocus() which is called after sending NOTIFY_IME_OF_FOCUS.
  367. if (!mIMEHasFocus) {
  368. MOZ_ASSERT(!mWidget || mNeedsToNotifyIMEOfFocusSet ||
  369. mSendingNotification == NOTIFY_IME_OF_FOCUS,
  370. "Wow, OnIMEReceivedFocus() won't be called?");
  371. return;
  372. }
  373. mIsObserving = true;
  374. if (mEditor) {
  375. mEditor->AddEditorObserver(this);
  376. }
  377. mUpdatePreference = mWidget->GetIMEUpdatePreference();
  378. if (!WasInitializedWithPlugin()) {
  379. // Add selection change listener only when this starts to observe
  380. // non-plugin content since we cannot detect selection changes in
  381. // plugins.
  382. nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
  383. NS_ENSURE_TRUE_VOID(selPrivate);
  384. nsresult rv = selPrivate->AddSelectionListener(this);
  385. NS_ENSURE_SUCCESS_VOID(rv);
  386. }
  387. if (mUpdatePreference.WantTextChange()) {
  388. // add text change observer
  389. mRootContent->AddMutationObserver(this);
  390. }
  391. if (mUpdatePreference.WantPositionChanged() && mDocShell) {
  392. // Add scroll position listener and reflow observer to detect position and
  393. // size changes
  394. mDocShell->AddWeakScrollObserver(this);
  395. mDocShell->AddWeakReflowObserver(this);
  396. }
  397. }
  398. void
  399. IMEContentObserver::NotifyIMEOfBlur()
  400. {
  401. // Prevent any notifications to be sent IME.
  402. nsCOMPtr<nsIWidget> widget;
  403. mWidget.swap(widget);
  404. // If we hasn't been set focus, we shouldn't send blur notification to IME.
  405. if (!mIMEHasFocus) {
  406. return;
  407. }
  408. // mWidget must have been non-nullptr if IME has focus.
  409. MOZ_RELEASE_ASSERT(widget);
  410. RefPtr<IMEContentObserver> kungFuDeathGrip(this);
  411. MOZ_LOG(sIMECOLog, LogLevel::Info,
  412. ("0x%p IMEContentObserver::NotifyIMEOfBlur(), "
  413. "sending NOTIFY_IME_OF_BLUR", this));
  414. // For now, we need to send blur notification in any condition because
  415. // we don't have any simple ways to send blur notification asynchronously.
  416. // After this call, Destroy() or Unlink() will stop observing the content
  417. // and forget everything. Therefore, if it's not safe to send notification
  418. // when script blocker is unlocked, we cannot send blur notification after
  419. // that and before next focus notification.
  420. // Anyway, as far as we know, IME doesn't try to query content when it loses
  421. // focus. So, this may not cause any problem.
  422. mIMEHasFocus = false;
  423. IMEStateManager::NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR), widget);
  424. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  425. ("0x%p IMEContentObserver::NotifyIMEOfBlur(), "
  426. "sent NOTIFY_IME_OF_BLUR", this));
  427. }
  428. void
  429. IMEContentObserver::UnregisterObservers()
  430. {
  431. if (!mIsObserving) {
  432. return;
  433. }
  434. mIsObserving = false;
  435. if (mEditor) {
  436. mEditor->RemoveEditorObserver(this);
  437. }
  438. if (mSelection) {
  439. nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
  440. if (selPrivate) {
  441. selPrivate->RemoveSelectionListener(this);
  442. }
  443. mSelectionData.Clear();
  444. mFocusedWidget = nullptr;
  445. }
  446. if (mUpdatePreference.WantTextChange() && mRootContent) {
  447. mRootContent->RemoveMutationObserver(this);
  448. }
  449. if (mUpdatePreference.WantPositionChanged() && mDocShell) {
  450. mDocShell->RemoveWeakScrollObserver(this);
  451. mDocShell->RemoveWeakReflowObserver(this);
  452. }
  453. }
  454. nsPresContext*
  455. IMEContentObserver::GetPresContext() const
  456. {
  457. return mESM ? mESM->GetPresContext() : nullptr;
  458. }
  459. void
  460. IMEContentObserver::Destroy()
  461. {
  462. // WARNING: When you change this method, you have to check Unlink() too.
  463. NotifyIMEOfBlur();
  464. UnregisterObservers();
  465. Clear();
  466. mWidget = nullptr;
  467. mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
  468. if (mESM) {
  469. mESM->OnStopObservingContent(this);
  470. mESM = nullptr;
  471. }
  472. }
  473. bool
  474. IMEContentObserver::Destroyed() const
  475. {
  476. return !mWidget;
  477. }
  478. void
  479. IMEContentObserver::DisconnectFromEventStateManager()
  480. {
  481. mESM = nullptr;
  482. }
  483. bool
  484. IMEContentObserver::MaybeReinitialize(nsIWidget* aWidget,
  485. nsPresContext* aPresContext,
  486. nsIContent* aContent,
  487. nsIEditor* aEditor)
  488. {
  489. if (!IsObservingContent(aPresContext, aContent)) {
  490. return false;
  491. }
  492. if (GetState() == eState_StoppedObserving) {
  493. Init(aWidget, aPresContext, aContent, aEditor);
  494. }
  495. return IsManaging(aPresContext, aContent);
  496. }
  497. bool
  498. IMEContentObserver::IsManaging(nsPresContext* aPresContext,
  499. nsIContent* aContent) const
  500. {
  501. return GetState() == eState_Observing &&
  502. IsObservingContent(aPresContext, aContent);
  503. }
  504. bool
  505. IMEContentObserver::IsManaging(const TextComposition* aComposition) const
  506. {
  507. if (GetState() != eState_Observing) {
  508. return false;
  509. }
  510. nsPresContext* presContext = aComposition->GetPresContext();
  511. if (NS_WARN_IF(!presContext)) {
  512. return false;
  513. }
  514. if (presContext != GetPresContext()) {
  515. return false; // observing different document
  516. }
  517. nsINode* targetNode = aComposition->GetEventTargetNode();
  518. nsIContent* targetContent =
  519. targetNode && targetNode->IsContent() ? targetNode->AsContent() : nullptr;
  520. return IsObservingContent(presContext, targetContent);
  521. }
  522. IMEContentObserver::State
  523. IMEContentObserver::GetState() const
  524. {
  525. if (!mSelection || !mRootContent || !mEditableNode) {
  526. return eState_NotObserving; // failed to initialize or finalized.
  527. }
  528. if (!mRootContent->IsInComposedDoc()) {
  529. // the focused editor has already been reframed.
  530. return eState_StoppedObserving;
  531. }
  532. return mIsObserving ? eState_Observing : eState_Initializing;
  533. }
  534. bool
  535. IMEContentObserver::IsObservingContent(nsPresContext* aPresContext,
  536. nsIContent* aContent) const
  537. {
  538. return IsInitializedWithPlugin() ?
  539. mRootContent == aContent && mRootContent != nullptr :
  540. mEditableNode == IMEStateManager::GetRootEditableNode(aPresContext,
  541. aContent);
  542. }
  543. bool
  544. IMEContentObserver::IsEditorHandlingEventForComposition() const
  545. {
  546. if (!mWidget) {
  547. return false;
  548. }
  549. RefPtr<TextComposition> composition =
  550. IMEStateManager::GetTextCompositionFor(mWidget);
  551. if (!composition) {
  552. return false;
  553. }
  554. return composition->IsEditorHandlingEvent();
  555. }
  556. bool
  557. IMEContentObserver::IsEditorComposing() const
  558. {
  559. // Note that don't use TextComposition here. The important thing is,
  560. // whether the editor already started to handle composition because
  561. // web contents can change selection, text content and/or something from
  562. // compositionstart event listener which is run before EditorBase handles it.
  563. nsCOMPtr<nsIEditorIMESupport> editorIMESupport = do_QueryInterface(mEditor);
  564. if (NS_WARN_IF(!editorIMESupport)) {
  565. return false;
  566. }
  567. bool isComposing = false;
  568. nsresult rv = editorIMESupport->GetComposing(&isComposing);
  569. if (NS_WARN_IF(NS_FAILED(rv))) {
  570. return false;
  571. }
  572. return isComposing;
  573. }
  574. nsresult
  575. IMEContentObserver::GetSelectionAndRoot(nsISelection** aSelection,
  576. nsIContent** aRootContent) const
  577. {
  578. if (!mEditableNode || !mSelection) {
  579. return NS_ERROR_NOT_AVAILABLE;
  580. }
  581. NS_ASSERTION(mSelection && mRootContent, "uninitialized content observer");
  582. NS_ADDREF(*aSelection = mSelection);
  583. NS_ADDREF(*aRootContent = mRootContent);
  584. return NS_OK;
  585. }
  586. nsresult
  587. IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
  588. nsISelection* aSelection,
  589. int16_t aReason)
  590. {
  591. int32_t count = 0;
  592. nsresult rv = aSelection->GetRangeCount(&count);
  593. NS_ENSURE_SUCCESS(rv, rv);
  594. if (count > 0 && mWidget) {
  595. bool causedByComposition = IsEditorHandlingEventForComposition();
  596. bool causedBySelectionEvent = TextComposition::IsHandlingSelectionEvent();
  597. bool duringComposition = IsEditorComposing();
  598. MaybeNotifyIMEOfSelectionChange(causedByComposition,
  599. causedBySelectionEvent,
  600. duringComposition);
  601. }
  602. return NS_OK;
  603. }
  604. void
  605. IMEContentObserver::ScrollPositionChanged()
  606. {
  607. MaybeNotifyIMEOfPositionChange();
  608. }
  609. NS_IMETHODIMP
  610. IMEContentObserver::Reflow(DOMHighResTimeStamp aStart,
  611. DOMHighResTimeStamp aEnd)
  612. {
  613. MaybeNotifyIMEOfPositionChange();
  614. return NS_OK;
  615. }
  616. NS_IMETHODIMP
  617. IMEContentObserver::ReflowInterruptible(DOMHighResTimeStamp aStart,
  618. DOMHighResTimeStamp aEnd)
  619. {
  620. MaybeNotifyIMEOfPositionChange();
  621. return NS_OK;
  622. }
  623. nsresult
  624. IMEContentObserver::HandleQueryContentEvent(WidgetQueryContentEvent* aEvent)
  625. {
  626. // If the instance has normal selection cache and the query event queries
  627. // normal selection's range, it should use the cached selection which was
  628. // sent to the widget. However, if this instance has already received new
  629. // selection change notification but hasn't updated the cache yet (i.e.,
  630. // not sending selection change notification to IME, don't use the cached
  631. // value. Note that don't update selection cache here since if you update
  632. // selection cache here, IMENotificationSender won't notify IME of selection
  633. // change because it looks like that the selection isn't actually changed.
  634. bool isSelectionCacheAvailable =
  635. aEvent->mUseNativeLineBreak && mSelectionData.IsValid() &&
  636. !mNeedsToNotifyIMEOfSelectionChange;
  637. if (isSelectionCacheAvailable &&
  638. aEvent->mMessage == eQuerySelectedText &&
  639. aEvent->mInput.mSelectionType == SelectionType::eNormal) {
  640. aEvent->mReply.mContentsRoot = mRootContent;
  641. aEvent->mReply.mHasSelection = !mSelectionData.IsCollapsed();
  642. aEvent->mReply.mOffset = mSelectionData.mOffset;
  643. aEvent->mReply.mString = mSelectionData.String();
  644. aEvent->mReply.mWritingMode = mSelectionData.GetWritingMode();
  645. aEvent->mReply.mReversed = mSelectionData.mReversed;
  646. aEvent->mSucceeded = true;
  647. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  648. ("0x%p IMEContentObserver::HandleQueryContentEvent(aEvent={ "
  649. "mMessage=%s })", this, ToChar(aEvent->mMessage)));
  650. return NS_OK;
  651. }
  652. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  653. ("0x%p IMEContentObserver::HandleQueryContentEvent(aEvent={ "
  654. "mMessage=%s })", this, ToChar(aEvent->mMessage)));
  655. // If we can make the event's input offset absolute with TextComposition or
  656. // mSelection, we should set it here for reducing the cost of computing
  657. // selection start offset. If ContentEventHandler receives a
  658. // WidgetQueryContentEvent whose input offset is relative to insertion point,
  659. // it computes current selection start offset (this may be expensive) and
  660. // make the offset absolute value itself.
  661. // Note that calling MakeOffsetAbsolute() makes the event a query event with
  662. // absolute offset. So, ContentEventHandler doesn't pay any additional cost
  663. // after calling MakeOffsetAbsolute() here.
  664. if (aEvent->mInput.mRelativeToInsertionPoint &&
  665. aEvent->mInput.IsValidEventMessage(aEvent->mMessage)) {
  666. RefPtr<TextComposition> composition =
  667. IMEStateManager::GetTextCompositionFor(aEvent->mWidget);
  668. if (composition) {
  669. uint32_t compositionStart = composition->NativeOffsetOfStartComposition();
  670. if (NS_WARN_IF(!aEvent->mInput.MakeOffsetAbsolute(compositionStart))) {
  671. return NS_ERROR_FAILURE;
  672. }
  673. } else if (isSelectionCacheAvailable) {
  674. uint32_t selectionStart = mSelectionData.mOffset;
  675. if (NS_WARN_IF(!aEvent->mInput.MakeOffsetAbsolute(selectionStart))) {
  676. return NS_ERROR_FAILURE;
  677. }
  678. }
  679. }
  680. AutoRestore<bool> handling(mIsHandlingQueryContentEvent);
  681. mIsHandlingQueryContentEvent = true;
  682. ContentEventHandler handler(GetPresContext());
  683. nsresult rv = handler.HandleQueryContentEvent(aEvent);
  684. if (NS_WARN_IF(Destroyed())) {
  685. // If this has already destroyed during querying the content, the query
  686. // is outdated even if it's succeeded. So, make the query fail.
  687. aEvent->mSucceeded = false;
  688. MOZ_LOG(sIMECOLog, LogLevel::Warning,
  689. ("0x%p IMEContentObserver::HandleQueryContentEvent(), WARNING, "
  690. "IMEContentObserver has been destroyed during the query, "
  691. "making the query fail", this));
  692. return rv;
  693. }
  694. if (!IsInitializedWithPlugin() &&
  695. NS_WARN_IF(aEvent->mReply.mContentsRoot != mRootContent)) {
  696. // Focus has changed unexpectedly, so make the query fail.
  697. aEvent->mSucceeded = false;
  698. }
  699. return rv;
  700. }
  701. bool
  702. IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
  703. WidgetMouseEvent* aMouseEvent)
  704. {
  705. if (!mUpdatePreference.WantMouseButtonEventOnChar()) {
  706. return false;
  707. }
  708. if (!aMouseEvent->IsTrusted() ||
  709. aMouseEvent->DefaultPrevented() ||
  710. !aMouseEvent->mWidget) {
  711. return false;
  712. }
  713. // Now, we need to notify only mouse down and mouse up event.
  714. switch (aMouseEvent->mMessage) {
  715. case eMouseUp:
  716. case eMouseDown:
  717. break;
  718. default:
  719. return false;
  720. }
  721. if (NS_WARN_IF(!mWidget) || NS_WARN_IF(mWidget->Destroyed())) {
  722. return false;
  723. }
  724. RefPtr<IMEContentObserver> kungFuDeathGrip(this);
  725. WidgetQueryContentEvent charAtPt(true, eQueryCharacterAtPoint,
  726. aMouseEvent->mWidget);
  727. charAtPt.mRefPoint = aMouseEvent->mRefPoint;
  728. ContentEventHandler handler(aPresContext);
  729. handler.OnQueryCharacterAtPoint(&charAtPt);
  730. if (NS_WARN_IF(!charAtPt.mSucceeded) ||
  731. charAtPt.mReply.mOffset == WidgetQueryContentEvent::NOT_FOUND) {
  732. return false;
  733. }
  734. // The widget might be destroyed during querying the content since it
  735. // causes flushing layout.
  736. if (!mWidget || NS_WARN_IF(mWidget->Destroyed())) {
  737. return false;
  738. }
  739. // The result character rect is relative to the top level widget.
  740. // We should notify it with offset in the widget.
  741. nsIWidget* topLevelWidget = mWidget->GetTopLevelWidget();
  742. if (topLevelWidget && topLevelWidget != mWidget) {
  743. charAtPt.mReply.mRect.MoveBy(
  744. topLevelWidget->WidgetToScreenOffset() -
  745. mWidget->WidgetToScreenOffset());
  746. }
  747. // The refPt is relative to its widget.
  748. // We should notify it with offset in the widget.
  749. if (aMouseEvent->mWidget != mWidget) {
  750. charAtPt.mRefPoint += aMouseEvent->mWidget->WidgetToScreenOffset() -
  751. mWidget->WidgetToScreenOffset();
  752. }
  753. IMENotification notification(NOTIFY_IME_OF_MOUSE_BUTTON_EVENT);
  754. notification.mMouseButtonEventData.mEventMessage = aMouseEvent->mMessage;
  755. notification.mMouseButtonEventData.mOffset = charAtPt.mReply.mOffset;
  756. notification.mMouseButtonEventData.mCursorPos.Set(
  757. charAtPt.mRefPoint.ToUnknownPoint());
  758. notification.mMouseButtonEventData.mCharRect.Set(
  759. charAtPt.mReply.mRect.ToUnknownRect());
  760. notification.mMouseButtonEventData.mButton = aMouseEvent->button;
  761. notification.mMouseButtonEventData.mButtons = aMouseEvent->buttons;
  762. notification.mMouseButtonEventData.mModifiers = aMouseEvent->mModifiers;
  763. nsresult rv = IMEStateManager::NotifyIME(notification, mWidget);
  764. if (NS_WARN_IF(NS_FAILED(rv))) {
  765. return false;
  766. }
  767. bool consumed = (rv == NS_SUCCESS_EVENT_CONSUMED);
  768. if (consumed) {
  769. aMouseEvent->PreventDefault();
  770. }
  771. return consumed;
  772. }
  773. void
  774. IMEContentObserver::CharacterDataWillChange(nsIDocument* aDocument,
  775. nsIContent* aContent,
  776. CharacterDataChangeInfo* aInfo)
  777. {
  778. NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
  779. "character data changed for non-text node");
  780. MOZ_ASSERT(mPreCharacterDataChangeLength < 0,
  781. "CharacterDataChanged() should've reset "
  782. "mPreCharacterDataChangeLength");
  783. mEndOfAddedTextCache.Clear();
  784. mStartOfRemovingTextRangeCache.Clear();
  785. mPreCharacterDataChangeLength =
  786. ContentEventHandler::GetNativeTextLength(aContent, aInfo->mChangeStart,
  787. aInfo->mChangeEnd);
  788. MOZ_ASSERT(mPreCharacterDataChangeLength >=
  789. aInfo->mChangeEnd - aInfo->mChangeStart,
  790. "The computed length must be same as or larger than XP length");
  791. }
  792. void
  793. IMEContentObserver::CharacterDataChanged(nsIDocument* aDocument,
  794. nsIContent* aContent,
  795. CharacterDataChangeInfo* aInfo)
  796. {
  797. NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
  798. "character data changed for non-text node");
  799. mEndOfAddedTextCache.Clear();
  800. mStartOfRemovingTextRangeCache.Clear();
  801. int64_t removedLength = mPreCharacterDataChangeLength;
  802. mPreCharacterDataChangeLength = -1;
  803. MOZ_ASSERT(removedLength >= 0,
  804. "mPreCharacterDataChangeLength should've been set by "
  805. "CharacterDataWillChange()");
  806. uint32_t offset = 0;
  807. // get offsets of change and fire notification
  808. nsresult rv =
  809. ContentEventHandler::GetFlatTextLengthInRange(
  810. NodePosition(mRootContent, 0),
  811. NodePosition(aContent, aInfo->mChangeStart),
  812. mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
  813. if (NS_WARN_IF(NS_FAILED(rv))) {
  814. return;
  815. }
  816. uint32_t newLength =
  817. ContentEventHandler::GetNativeTextLength(aContent, aInfo->mChangeStart,
  818. aInfo->mChangeStart +
  819. aInfo->mReplaceLength);
  820. uint32_t oldEnd = offset + static_cast<uint32_t>(removedLength);
  821. uint32_t newEnd = offset + newLength;
  822. TextChangeData data(offset, oldEnd, newEnd,
  823. IsEditorHandlingEventForComposition(),
  824. IsEditorComposing());
  825. MaybeNotifyIMEOfTextChange(data);
  826. }
  827. void
  828. IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
  829. int32_t aStartIndex,
  830. int32_t aEndIndex)
  831. {
  832. mStartOfRemovingTextRangeCache.Clear();
  833. uint32_t offset = 0;
  834. nsresult rv = NS_OK;
  835. if (!mEndOfAddedTextCache.Match(aContainer, aStartIndex)) {
  836. mEndOfAddedTextCache.Clear();
  837. rv = ContentEventHandler::GetFlatTextLengthInRange(
  838. NodePosition(mRootContent, 0),
  839. NodePositionBefore(aContainer, aStartIndex),
  840. mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
  841. if (NS_WARN_IF(NS_FAILED((rv)))) {
  842. return;
  843. }
  844. } else {
  845. offset = mEndOfAddedTextCache.mFlatTextLength;
  846. }
  847. // get offset at the end of the last added node
  848. uint32_t addingLength = 0;
  849. rv = ContentEventHandler::GetFlatTextLengthInRange(
  850. NodePositionBefore(aContainer, aStartIndex),
  851. NodePosition(aContainer, aEndIndex),
  852. mRootContent, &addingLength,
  853. LINE_BREAK_TYPE_NATIVE);
  854. if (NS_WARN_IF(NS_FAILED((rv)))) {
  855. mEndOfAddedTextCache.Clear();
  856. return;
  857. }
  858. // If multiple lines are being inserted in an HTML editor, next call of
  859. // NotifyContentAdded() is for adding next node. Therefore, caching the text
  860. // length can skip to compute the text length before the adding node and
  861. // before of it.
  862. mEndOfAddedTextCache.Cache(aContainer, aEndIndex, offset + addingLength);
  863. if (!addingLength) {
  864. return;
  865. }
  866. TextChangeData data(offset, offset, offset + addingLength,
  867. IsEditorHandlingEventForComposition(),
  868. IsEditorComposing());
  869. MaybeNotifyIMEOfTextChange(data);
  870. }
  871. void
  872. IMEContentObserver::ContentAppended(nsIDocument* aDocument,
  873. nsIContent* aContainer,
  874. nsIContent* aFirstNewContent,
  875. int32_t aNewIndexInContainer)
  876. {
  877. NotifyContentAdded(aContainer, aNewIndexInContainer,
  878. aContainer->GetChildCount());
  879. }
  880. void
  881. IMEContentObserver::ContentInserted(nsIDocument* aDocument,
  882. nsIContent* aContainer,
  883. nsIContent* aChild,
  884. int32_t aIndexInContainer)
  885. {
  886. NotifyContentAdded(NODE_FROM(aContainer, aDocument),
  887. aIndexInContainer, aIndexInContainer + 1);
  888. }
  889. void
  890. IMEContentObserver::ContentRemoved(nsIDocument* aDocument,
  891. nsIContent* aContainer,
  892. nsIContent* aChild,
  893. int32_t aIndexInContainer,
  894. nsIContent* aPreviousSibling)
  895. {
  896. mEndOfAddedTextCache.Clear();
  897. nsINode* containerNode = NODE_FROM(aContainer, aDocument);
  898. uint32_t offset = 0;
  899. nsresult rv = NS_OK;
  900. if (!mStartOfRemovingTextRangeCache.Match(containerNode, aIndexInContainer)) {
  901. // At removing a child node of aContainer, we need the line break caused
  902. // by open tag of aContainer. Be careful when aIndexInContainer is 0.
  903. rv = ContentEventHandler::GetFlatTextLengthInRange(
  904. NodePosition(mRootContent, 0),
  905. NodePosition(containerNode, aIndexInContainer),
  906. mRootContent, &offset, LINE_BREAK_TYPE_NATIVE);
  907. if (NS_WARN_IF(NS_FAILED(rv))) {
  908. mStartOfRemovingTextRangeCache.Clear();
  909. return;
  910. }
  911. mStartOfRemovingTextRangeCache.Cache(containerNode, aIndexInContainer,
  912. offset);
  913. } else {
  914. offset = mStartOfRemovingTextRangeCache.mFlatTextLength;
  915. }
  916. // get offset at the end of the deleted node
  917. uint32_t textLength = 0;
  918. if (aChild->IsNodeOfType(nsINode::eTEXT)) {
  919. textLength = ContentEventHandler::GetNativeTextLength(aChild);
  920. } else {
  921. uint32_t nodeLength = static_cast<int32_t>(aChild->GetChildCount());
  922. rv = ContentEventHandler::GetFlatTextLengthInRange(
  923. NodePositionBefore(aChild, 0),
  924. NodePosition(aChild, nodeLength),
  925. mRootContent, &textLength,
  926. LINE_BREAK_TYPE_NATIVE, true);
  927. if (NS_WARN_IF(NS_FAILED(rv))) {
  928. mStartOfRemovingTextRangeCache.Clear();
  929. return;
  930. }
  931. }
  932. if (!textLength) {
  933. return;
  934. }
  935. TextChangeData data(offset, offset + textLength, offset,
  936. IsEditorHandlingEventForComposition(),
  937. IsEditorComposing());
  938. MaybeNotifyIMEOfTextChange(data);
  939. }
  940. void
  941. IMEContentObserver::AttributeWillChange(nsIDocument* aDocument,
  942. dom::Element* aElement,
  943. int32_t aNameSpaceID,
  944. nsIAtom* aAttribute,
  945. int32_t aModType,
  946. const nsAttrValue* aNewValue)
  947. {
  948. mPreAttrChangeLength =
  949. ContentEventHandler::GetNativeTextLengthBefore(aElement, mRootContent);
  950. }
  951. void
  952. IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
  953. dom::Element* aElement,
  954. int32_t aNameSpaceID,
  955. nsIAtom* aAttribute,
  956. int32_t aModType,
  957. const nsAttrValue* aOldValue)
  958. {
  959. mEndOfAddedTextCache.Clear();
  960. mStartOfRemovingTextRangeCache.Clear();
  961. uint32_t postAttrChangeLength =
  962. ContentEventHandler::GetNativeTextLengthBefore(aElement, mRootContent);
  963. if (postAttrChangeLength == mPreAttrChangeLength) {
  964. return;
  965. }
  966. uint32_t start;
  967. nsresult rv =
  968. ContentEventHandler::GetFlatTextLengthInRange(
  969. NodePosition(mRootContent, 0),
  970. NodePositionBefore(aElement, 0),
  971. mRootContent, &start, LINE_BREAK_TYPE_NATIVE);
  972. if (NS_WARN_IF(NS_FAILED(rv))) {
  973. return;
  974. }
  975. TextChangeData data(start, start + mPreAttrChangeLength,
  976. start + postAttrChangeLength,
  977. IsEditorHandlingEventForComposition(),
  978. IsEditorComposing());
  979. MaybeNotifyIMEOfTextChange(data);
  980. }
  981. void
  982. IMEContentObserver::SuppressNotifyingIME()
  983. {
  984. mSuppressNotifications++;
  985. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  986. ("0x%p IMEContentObserver::SuppressNotifyingIME(), "
  987. "mSuppressNotifications=%u", this, mSuppressNotifications));
  988. }
  989. void
  990. IMEContentObserver::UnsuppressNotifyingIME()
  991. {
  992. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  993. ("0x%p IMEContentObserver::UnsuppressNotifyingIME(), "
  994. "mSuppressNotifications=%u", this, mSuppressNotifications));
  995. if (!mSuppressNotifications || --mSuppressNotifications) {
  996. return;
  997. }
  998. FlushMergeableNotifications();
  999. }
  1000. NS_IMETHODIMP
  1001. IMEContentObserver::EditAction()
  1002. {
  1003. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1004. ("0x%p IMEContentObserver::EditAction()", this));
  1005. mEndOfAddedTextCache.Clear();
  1006. mStartOfRemovingTextRangeCache.Clear();
  1007. FlushMergeableNotifications();
  1008. return NS_OK;
  1009. }
  1010. NS_IMETHODIMP
  1011. IMEContentObserver::BeforeEditAction()
  1012. {
  1013. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1014. ("0x%p IMEContentObserver::BeforeEditAction()", this));
  1015. mEndOfAddedTextCache.Clear();
  1016. mStartOfRemovingTextRangeCache.Clear();
  1017. return NS_OK;
  1018. }
  1019. NS_IMETHODIMP
  1020. IMEContentObserver::CancelEditAction()
  1021. {
  1022. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1023. ("0x%p IMEContentObserver::CancelEditAction()", this));
  1024. mEndOfAddedTextCache.Clear();
  1025. mStartOfRemovingTextRangeCache.Clear();
  1026. FlushMergeableNotifications();
  1027. return NS_OK;
  1028. }
  1029. void
  1030. IMEContentObserver::PostFocusSetNotification()
  1031. {
  1032. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1033. ("0x%p IMEContentObserver::PostFocusSetNotification()", this));
  1034. mNeedsToNotifyIMEOfFocusSet = true;
  1035. }
  1036. void
  1037. IMEContentObserver::PostTextChangeNotification()
  1038. {
  1039. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1040. ("0x%p IMEContentObserver::PostTextChangeNotification("
  1041. "mTextChangeData=%s)",
  1042. this, TextChangeDataToString(mTextChangeData).get()));
  1043. MOZ_ASSERT(mTextChangeData.IsValid(),
  1044. "mTextChangeData must have text change data");
  1045. mNeedsToNotifyIMEOfTextChange = true;
  1046. }
  1047. void
  1048. IMEContentObserver::PostSelectionChangeNotification()
  1049. {
  1050. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1051. ("0x%p IMEContentObserver::PostSelectionChangeNotification(), "
  1052. "mSelectionData={ mCausedByComposition=%s, mCausedBySelectionEvent=%s }",
  1053. this, ToChar(mSelectionData.mCausedByComposition),
  1054. ToChar(mSelectionData.mCausedBySelectionEvent)));
  1055. mNeedsToNotifyIMEOfSelectionChange = true;
  1056. }
  1057. void
  1058. IMEContentObserver::MaybeNotifyIMEOfFocusSet()
  1059. {
  1060. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1061. ("0x%p IMEContentObserver::MaybeNotifyIMEOfFocusSet()", this));
  1062. PostFocusSetNotification();
  1063. FlushMergeableNotifications();
  1064. }
  1065. void
  1066. IMEContentObserver::MaybeNotifyIMEOfTextChange(
  1067. const TextChangeDataBase& aTextChangeData)
  1068. {
  1069. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1070. ("0x%p IMEContentObserver::MaybeNotifyIMEOfTextChange("
  1071. "aTextChangeData=%s)",
  1072. this, TextChangeDataToString(aTextChangeData).get()));
  1073. mTextChangeData += aTextChangeData;
  1074. PostTextChangeNotification();
  1075. FlushMergeableNotifications();
  1076. }
  1077. void
  1078. IMEContentObserver::MaybeNotifyIMEOfSelectionChange(
  1079. bool aCausedByComposition,
  1080. bool aCausedBySelectionEvent,
  1081. bool aOccurredDuringComposition)
  1082. {
  1083. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1084. ("0x%p IMEContentObserver::MaybeNotifyIMEOfSelectionChange("
  1085. "aCausedByComposition=%s, aCausedBySelectionEvent=%s, "
  1086. "aOccurredDuringComposition)",
  1087. this, ToChar(aCausedByComposition), ToChar(aCausedBySelectionEvent)));
  1088. mSelectionData.AssignReason(aCausedByComposition,
  1089. aCausedBySelectionEvent,
  1090. aOccurredDuringComposition);
  1091. PostSelectionChangeNotification();
  1092. FlushMergeableNotifications();
  1093. }
  1094. void
  1095. IMEContentObserver::MaybeNotifyIMEOfPositionChange()
  1096. {
  1097. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1098. ("0x%p IMEContentObserver::MaybeNotifyIMEOfPositionChange()", this));
  1099. // If reflow is caused by ContentEventHandler during PositionChangeEvent
  1100. // sending NOTIFY_IME_OF_POSITION_CHANGE, we don't need to notify IME of it
  1101. // again since ContentEventHandler returns the result including this reflow's
  1102. // result.
  1103. if (mIsHandlingQueryContentEvent &&
  1104. mSendingNotification == NOTIFY_IME_OF_POSITION_CHANGE) {
  1105. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1106. ("0x%p IMEContentObserver::MaybeNotifyIMEOfPositionChange(), "
  1107. "ignored since caused by ContentEventHandler during sending "
  1108. "NOTIY_IME_OF_POSITION_CHANGE", this));
  1109. return;
  1110. }
  1111. PostPositionChangeNotification();
  1112. FlushMergeableNotifications();
  1113. }
  1114. void
  1115. IMEContentObserver::MaybeNotifyCompositionEventHandled()
  1116. {
  1117. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1118. ("0x%p IMEContentObserver::MaybeNotifyCompositionEventHandled()",
  1119. this));
  1120. PostCompositionEventHandledNotification();
  1121. FlushMergeableNotifications();
  1122. }
  1123. bool
  1124. IMEContentObserver::UpdateSelectionCache()
  1125. {
  1126. MOZ_ASSERT(IsSafeToNotifyIME());
  1127. if (WasInitializedWithPlugin()) {
  1128. return false;
  1129. }
  1130. mSelectionData.ClearSelectionData();
  1131. // XXX Cannot we cache some information for reducing the cost to compute
  1132. // selection offset and writing mode?
  1133. WidgetQueryContentEvent selection(true, eQuerySelectedText, mWidget);
  1134. ContentEventHandler handler(GetPresContext());
  1135. handler.OnQuerySelectedText(&selection);
  1136. if (NS_WARN_IF(!selection.mSucceeded) ||
  1137. NS_WARN_IF(selection.mReply.mContentsRoot != mRootContent)) {
  1138. return false;
  1139. }
  1140. mFocusedWidget = selection.mReply.mFocusedWidget;
  1141. mSelectionData.mOffset = selection.mReply.mOffset;
  1142. *mSelectionData.mString = selection.mReply.mString;
  1143. mSelectionData.SetWritingMode(selection.GetWritingMode());
  1144. mSelectionData.mReversed = selection.mReply.mReversed;
  1145. // WARNING: Don't modify the reason of selection change here.
  1146. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1147. ("0x%p IMEContentObserver::UpdateSelectionCache(), "
  1148. "mSelectionData=%s",
  1149. this, SelectionChangeDataToString(mSelectionData).get()));
  1150. return mSelectionData.IsValid();
  1151. }
  1152. void
  1153. IMEContentObserver::PostPositionChangeNotification()
  1154. {
  1155. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1156. ("0x%p IMEContentObserver::PostPositionChangeNotification()", this));
  1157. mNeedsToNotifyIMEOfPositionChange = true;
  1158. }
  1159. void
  1160. IMEContentObserver::PostCompositionEventHandledNotification()
  1161. {
  1162. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1163. ("0x%p IMEContentObserver::"
  1164. "PostCompositionEventHandledNotification()", this));
  1165. mNeedsToNotifyIMEOfCompositionEventHandled = true;
  1166. }
  1167. bool
  1168. IMEContentObserver::IsReflowLocked() const
  1169. {
  1170. nsPresContext* presContext = GetPresContext();
  1171. if (NS_WARN_IF(!presContext)) {
  1172. return false;
  1173. }
  1174. nsIPresShell* presShell = presContext->GetPresShell();
  1175. if (NS_WARN_IF(!presShell)) {
  1176. return false;
  1177. }
  1178. // During reflow, we shouldn't notify IME because IME may query content
  1179. // synchronously. Then, it causes ContentEventHandler will try to flush
  1180. // pending notifications during reflow.
  1181. return presShell->IsReflowLocked();
  1182. }
  1183. bool
  1184. IMEContentObserver::IsSafeToNotifyIME() const
  1185. {
  1186. // If this is already detached from the widget, this doesn't need to notify
  1187. // anything.
  1188. if (!mWidget) {
  1189. return false;
  1190. }
  1191. // Don't notify IME of anything if it's not good time to do it.
  1192. if (mSuppressNotifications) {
  1193. return false;
  1194. }
  1195. if (!mESM || NS_WARN_IF(!GetPresContext())) {
  1196. return false;
  1197. }
  1198. // If it's in reflow, we should wait to finish the reflow.
  1199. // FYI: This should be called again from Reflow() or ReflowInterruptible().
  1200. if (IsReflowLocked()) {
  1201. return false;
  1202. }
  1203. // If we're in handling an edit action, this method will be called later.
  1204. bool isInEditAction = false;
  1205. if (mEditor && NS_SUCCEEDED(mEditor->GetIsInEditAction(&isInEditAction)) &&
  1206. isInEditAction) {
  1207. return false;
  1208. }
  1209. return true;
  1210. }
  1211. void
  1212. IMEContentObserver::FlushMergeableNotifications()
  1213. {
  1214. if (!IsSafeToNotifyIME()) {
  1215. // So, if this is already called, this should do nothing.
  1216. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1217. ("0x%p IMEContentObserver::FlushMergeableNotifications(), "
  1218. "FAILED, due to unsafe to notify IME", this));
  1219. return;
  1220. }
  1221. // Notifying something may cause nested call of this method. For example,
  1222. // when somebody notified one of the notifications may dispatch query content
  1223. // event. Then, it causes flushing layout which may cause another layout
  1224. // change notification.
  1225. if (mQueuedSender) {
  1226. // So, if this is already called, this should do nothing.
  1227. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1228. ("0x%p IMEContentObserver::FlushMergeableNotifications(), "
  1229. "FAILED, due to already flushing pending notifications", this));
  1230. return;
  1231. }
  1232. if (!NeedsToNotifyIMEOfSomething()) {
  1233. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1234. ("0x%p IMEContentObserver::FlushMergeableNotifications(), "
  1235. "FAILED, due to no pending notifications", this));
  1236. return;
  1237. }
  1238. // NOTE: Reset each pending flag because sending notification may cause
  1239. // another change.
  1240. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1241. ("0x%p IMEContentObserver::FlushMergeableNotifications(), "
  1242. "creating IMENotificationSender...", this));
  1243. // If contents in selection range is modified, the selection range still
  1244. // has removed node from the tree. In such case, nsContentIterator won't
  1245. // work well. Therefore, we shouldn't use AddScriptRunnder() here since
  1246. // it may kick runnable event immediately after DOM tree is changed but
  1247. // the selection range isn't modified yet.
  1248. mQueuedSender = new IMENotificationSender(this);
  1249. NS_DispatchToCurrentThread(mQueuedSender);
  1250. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1251. ("0x%p IMEContentObserver::FlushMergeableNotifications(), "
  1252. "finished", this));
  1253. }
  1254. void
  1255. IMEContentObserver::TryToFlushPendingNotifications()
  1256. {
  1257. if (!mQueuedSender || mSendingNotification != NOTIFY_IME_OF_NOTHING) {
  1258. return;
  1259. }
  1260. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1261. ("0x%p IMEContentObserver::TryToFlushPendingNotifications(), "
  1262. "performing queued IMENotificationSender forcibly", this));
  1263. RefPtr<IMENotificationSender> queuedSender = mQueuedSender;
  1264. queuedSender->Run();
  1265. }
  1266. /******************************************************************************
  1267. * mozilla::IMEContentObserver::AChangeEvent
  1268. ******************************************************************************/
  1269. bool
  1270. IMEContentObserver::AChangeEvent::CanNotifyIME(
  1271. ChangeEventType aChangeEventType) const
  1272. {
  1273. if (NS_WARN_IF(!mIMEContentObserver)) {
  1274. return false;
  1275. }
  1276. if (aChangeEventType == eChangeEventType_CompositionEventHandled) {
  1277. return mIMEContentObserver->mWidget != nullptr;
  1278. }
  1279. State state = mIMEContentObserver->GetState();
  1280. // If it's not initialized, we should do nothing.
  1281. if (state == eState_NotObserving) {
  1282. return false;
  1283. }
  1284. // If setting focus, just check the state.
  1285. if (aChangeEventType == eChangeEventType_Focus) {
  1286. return !NS_WARN_IF(mIMEContentObserver->mIMEHasFocus);
  1287. }
  1288. // If we've not notified IME of focus yet, we shouldn't notify anything.
  1289. if (!mIMEContentObserver->mIMEHasFocus) {
  1290. return false;
  1291. }
  1292. // If IME has focus, IMEContentObserver must hold the widget.
  1293. MOZ_ASSERT(mIMEContentObserver->mWidget);
  1294. return true;
  1295. }
  1296. bool
  1297. IMEContentObserver::AChangeEvent::IsSafeToNotifyIME(
  1298. ChangeEventType aChangeEventType) const
  1299. {
  1300. if (NS_WARN_IF(!nsContentUtils::IsSafeToRunScript())) {
  1301. return false;
  1302. }
  1303. // While we're sending a notification, we shouldn't send another notification
  1304. // recursively.
  1305. if (mIMEContentObserver->mSendingNotification != NOTIFY_IME_OF_NOTHING) {
  1306. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1307. ("0x%p IMEContentObserver::AChangeEvent::IsSafeToNotifyIME(), "
  1308. "putting off sending notification due to detecting recursive call, "
  1309. "mIMEContentObserver={ mSendingNotification=%s }",
  1310. this, ToChar(mIMEContentObserver->mSendingNotification)));
  1311. return false;
  1312. }
  1313. State state = mIMEContentObserver->GetState();
  1314. if (aChangeEventType == eChangeEventType_Focus) {
  1315. if (NS_WARN_IF(state != eState_Initializing && state != eState_Observing)) {
  1316. return false;
  1317. }
  1318. } else if (aChangeEventType == eChangeEventType_CompositionEventHandled) {
  1319. // It doesn't need to check the observing status.
  1320. } else if (state != eState_Observing) {
  1321. return false;
  1322. }
  1323. return mIMEContentObserver->IsSafeToNotifyIME();
  1324. }
  1325. /******************************************************************************
  1326. * mozilla::IMEContentObserver::IMENotificationSender
  1327. ******************************************************************************/
  1328. NS_IMETHODIMP
  1329. IMEContentObserver::IMENotificationSender::Run()
  1330. {
  1331. if (NS_WARN_IF(mIsRunning)) {
  1332. MOZ_LOG(sIMECOLog, LogLevel::Error,
  1333. ("0x%p IMEContentObserver::IMENotificationSender::Run(), FAILED, "
  1334. "called recursively", this));
  1335. return NS_OK;
  1336. }
  1337. AutoRestore<bool> running(mIsRunning);
  1338. mIsRunning = true;
  1339. // This instance was already performed forcibly.
  1340. if (mIMEContentObserver->mQueuedSender != this) {
  1341. return NS_OK;
  1342. }
  1343. // NOTE: Reset each pending flag because sending notification may cause
  1344. // another change.
  1345. if (mIMEContentObserver->mNeedsToNotifyIMEOfFocusSet) {
  1346. mIMEContentObserver->mNeedsToNotifyIMEOfFocusSet = false;
  1347. SendFocusSet();
  1348. mIMEContentObserver->mQueuedSender = nullptr;
  1349. // If it's not safe to notify IME of focus, SendFocusSet() sets
  1350. // mNeedsToNotifyIMEOfFocusSet true again. For guaranteeing to send the
  1351. // focus notification later, we should put a new sender into the queue but
  1352. // this case must be rare. Note that if mIMEContentObserver is already
  1353. // destroyed, mNeedsToNotifyIMEOfFocusSet is never set true again.
  1354. if (mIMEContentObserver->mNeedsToNotifyIMEOfFocusSet) {
  1355. MOZ_ASSERT(!mIMEContentObserver->mIMEHasFocus);
  1356. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1357. ("0x%p IMEContentObserver::IMENotificationSender::Run(), "
  1358. "posting IMENotificationSender to current thread", this));
  1359. mIMEContentObserver->mQueuedSender =
  1360. new IMENotificationSender(mIMEContentObserver);
  1361. NS_DispatchToCurrentThread(mIMEContentObserver->mQueuedSender);
  1362. return NS_OK;
  1363. }
  1364. // This is the first notification to IME. So, we don't need to notify
  1365. // anymore since IME starts to query content after it gets focus.
  1366. mIMEContentObserver->ClearPendingNotifications();
  1367. return NS_OK;
  1368. }
  1369. if (mIMEContentObserver->mNeedsToNotifyIMEOfTextChange) {
  1370. mIMEContentObserver->mNeedsToNotifyIMEOfTextChange = false;
  1371. SendTextChange();
  1372. }
  1373. // If a text change notification causes another text change again, we should
  1374. // notify IME of that before sending a selection change notification.
  1375. if (!mIMEContentObserver->mNeedsToNotifyIMEOfTextChange) {
  1376. // Be aware, PuppetWidget depends on the order of this. A selection change
  1377. // notification should not be sent before a text change notification because
  1378. // PuppetWidget shouldn't query new text content every selection change.
  1379. if (mIMEContentObserver->mNeedsToNotifyIMEOfSelectionChange) {
  1380. mIMEContentObserver->mNeedsToNotifyIMEOfSelectionChange = false;
  1381. SendSelectionChange();
  1382. }
  1383. }
  1384. // If a text change notification causes another text change again or a
  1385. // selection change notification causes either a text change or another
  1386. // selection change, we should notify IME of those before sending a position
  1387. // change notification.
  1388. if (!mIMEContentObserver->mNeedsToNotifyIMEOfTextChange &&
  1389. !mIMEContentObserver->mNeedsToNotifyIMEOfSelectionChange) {
  1390. if (mIMEContentObserver->mNeedsToNotifyIMEOfPositionChange) {
  1391. mIMEContentObserver->mNeedsToNotifyIMEOfPositionChange = false;
  1392. SendPositionChange();
  1393. }
  1394. }
  1395. // Composition event handled notification should be sent after all the
  1396. // other notifications because this notifies widget of finishing all pending
  1397. // events are handled completely.
  1398. if (!mIMEContentObserver->mNeedsToNotifyIMEOfTextChange &&
  1399. !mIMEContentObserver->mNeedsToNotifyIMEOfSelectionChange &&
  1400. !mIMEContentObserver->mNeedsToNotifyIMEOfPositionChange) {
  1401. if (mIMEContentObserver->mNeedsToNotifyIMEOfCompositionEventHandled) {
  1402. mIMEContentObserver->mNeedsToNotifyIMEOfCompositionEventHandled = false;
  1403. SendCompositionEventHandled();
  1404. }
  1405. }
  1406. mIMEContentObserver->mQueuedSender = nullptr;
  1407. // If notifications caused some new change, we should notify them now.
  1408. if (mIMEContentObserver->NeedsToNotifyIMEOfSomething()) {
  1409. if (mIMEContentObserver->GetState() == eState_StoppedObserving) {
  1410. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1411. ("0x%p IMEContentObserver::IMENotificationSender::Run(), "
  1412. "waiting IMENotificationSender to be reinitialized", this));
  1413. } else {
  1414. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1415. ("0x%p IMEContentObserver::IMENotificationSender::Run(), "
  1416. "posting IMENotificationSender to current thread", this));
  1417. mIMEContentObserver->mQueuedSender =
  1418. new IMENotificationSender(mIMEContentObserver);
  1419. NS_DispatchToCurrentThread(mIMEContentObserver->mQueuedSender);
  1420. }
  1421. }
  1422. return NS_OK;
  1423. }
  1424. void
  1425. IMEContentObserver::IMENotificationSender::SendFocusSet()
  1426. {
  1427. if (!CanNotifyIME(eChangeEventType_Focus)) {
  1428. // If IMEContentObserver has already gone, we don't need to notify IME of
  1429. // focus.
  1430. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1431. ("0x%p IMEContentObserver::IMENotificationSender::"
  1432. "SendFocusSet(), FAILED, due to impossible to notify IME of focus",
  1433. this));
  1434. mIMEContentObserver->ClearPendingNotifications();
  1435. return;
  1436. }
  1437. if (!IsSafeToNotifyIME(eChangeEventType_Focus)) {
  1438. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1439. ("0x%p IMEContentObserver::IMENotificationSender::"
  1440. "SendFocusSet(), retrying to send NOTIFY_IME_OF_FOCUS...", this));
  1441. mIMEContentObserver->PostFocusSetNotification();
  1442. return;
  1443. }
  1444. mIMEContentObserver->mIMEHasFocus = true;
  1445. // Initialize selection cache with the first selection data.
  1446. mIMEContentObserver->UpdateSelectionCache();
  1447. MOZ_LOG(sIMECOLog, LogLevel::Info,
  1448. ("0x%p IMEContentObserver::IMENotificationSender::"
  1449. "SendFocusSet(), sending NOTIFY_IME_OF_FOCUS...", this));
  1450. MOZ_RELEASE_ASSERT(mIMEContentObserver->mSendingNotification ==
  1451. NOTIFY_IME_OF_NOTHING);
  1452. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_FOCUS;
  1453. IMEStateManager::NotifyIME(IMENotification(NOTIFY_IME_OF_FOCUS),
  1454. mIMEContentObserver->mWidget);
  1455. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_NOTHING;
  1456. // nsIMEUpdatePreference referred by ObserveEditableNode() may be different
  1457. // before or after widget receives NOTIFY_IME_OF_FOCUS. Therefore, we need
  1458. // to guarantee to call ObserveEditableNode() after sending
  1459. // NOTIFY_IME_OF_FOCUS.
  1460. mIMEContentObserver->OnIMEReceivedFocus();
  1461. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1462. ("0x%p IMEContentObserver::IMENotificationSender::"
  1463. "SendFocusSet(), sent NOTIFY_IME_OF_FOCUS", this));
  1464. }
  1465. void
  1466. IMEContentObserver::IMENotificationSender::SendSelectionChange()
  1467. {
  1468. if (!CanNotifyIME(eChangeEventType_Selection)) {
  1469. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1470. ("0x%p IMEContentObserver::IMENotificationSender::"
  1471. "SendSelectionChange(), FAILED, due to impossible to notify IME of "
  1472. "selection change", this));
  1473. return;
  1474. }
  1475. if (!IsSafeToNotifyIME(eChangeEventType_Selection)) {
  1476. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1477. ("0x%p IMEContentObserver::IMENotificationSender::"
  1478. "SendSelectionChange(), retrying to send "
  1479. "NOTIFY_IME_OF_SELECTION_CHANGE...", this));
  1480. mIMEContentObserver->PostSelectionChangeNotification();
  1481. return;
  1482. }
  1483. SelectionChangeData lastSelChangeData = mIMEContentObserver->mSelectionData;
  1484. if (NS_WARN_IF(!mIMEContentObserver->UpdateSelectionCache())) {
  1485. MOZ_LOG(sIMECOLog, LogLevel::Error,
  1486. ("0x%p IMEContentObserver::IMENotificationSender::"
  1487. "SendSelectionChange(), FAILED, due to UpdateSelectionCache() failure",
  1488. this));
  1489. return;
  1490. }
  1491. // The state may be changed since querying content causes flushing layout.
  1492. if (!CanNotifyIME(eChangeEventType_Selection)) {
  1493. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1494. ("0x%p IMEContentObserver::IMENotificationSender::"
  1495. "SendSelectionChange(), FAILED, due to flushing layout having changed "
  1496. "something", this));
  1497. return;
  1498. }
  1499. // If the selection isn't changed actually, we shouldn't notify IME of
  1500. // selection change.
  1501. SelectionChangeData& newSelChangeData = mIMEContentObserver->mSelectionData;
  1502. if (lastSelChangeData.IsValid() &&
  1503. lastSelChangeData.mOffset == newSelChangeData.mOffset &&
  1504. lastSelChangeData.String() == newSelChangeData.String() &&
  1505. lastSelChangeData.GetWritingMode() == newSelChangeData.GetWritingMode() &&
  1506. lastSelChangeData.mReversed == newSelChangeData.mReversed) {
  1507. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1508. ("0x%p IMEContentObserver::IMENotificationSender::"
  1509. "SendSelectionChange(), not notifying IME of "
  1510. "NOTIFY_IME_OF_SELECTION_CHANGE due to not changed actually", this));
  1511. return;
  1512. }
  1513. MOZ_LOG(sIMECOLog, LogLevel::Info,
  1514. ("0x%p IMEContentObserver::IMENotificationSender::"
  1515. "SendSelectionChange(), sending NOTIFY_IME_OF_SELECTION_CHANGE... "
  1516. "newSelChangeData=%s",
  1517. this, SelectionChangeDataToString(newSelChangeData).get()));
  1518. IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
  1519. notification.SetData(mIMEContentObserver->mSelectionData);
  1520. MOZ_RELEASE_ASSERT(mIMEContentObserver->mSendingNotification ==
  1521. NOTIFY_IME_OF_NOTHING);
  1522. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_SELECTION_CHANGE;
  1523. IMEStateManager::NotifyIME(notification, mIMEContentObserver->mWidget);
  1524. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_NOTHING;
  1525. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1526. ("0x%p IMEContentObserver::IMENotificationSender::"
  1527. "SendSelectionChange(), sent NOTIFY_IME_OF_SELECTION_CHANGE", this));
  1528. }
  1529. void
  1530. IMEContentObserver::IMENotificationSender::SendTextChange()
  1531. {
  1532. if (!CanNotifyIME(eChangeEventType_Text)) {
  1533. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1534. ("0x%p IMEContentObserver::IMENotificationSender::"
  1535. "SendTextChange(), FAILED, due to impossible to notify IME of text "
  1536. "change", this));
  1537. return;
  1538. }
  1539. if (!IsSafeToNotifyIME(eChangeEventType_Text)) {
  1540. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1541. ("0x%p IMEContentObserver::IMENotificationSender::"
  1542. "SendTextChange(), retrying to send NOTIFY_IME_OF_TEXT_CHANGE...",
  1543. this));
  1544. mIMEContentObserver->PostTextChangeNotification();
  1545. return;
  1546. }
  1547. MOZ_LOG(sIMECOLog, LogLevel::Info,
  1548. ("0x%p IMEContentObserver::IMENotificationSender::"
  1549. "SendTextChange(), sending NOTIFY_IME_OF_TEXT_CHANGE... "
  1550. "mIMEContentObserver={ mTextChangeData=%s }",
  1551. this, TextChangeDataToString(mIMEContentObserver->mTextChangeData).get()));
  1552. IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
  1553. notification.SetData(mIMEContentObserver->mTextChangeData);
  1554. mIMEContentObserver->mTextChangeData.Clear();
  1555. MOZ_RELEASE_ASSERT(mIMEContentObserver->mSendingNotification ==
  1556. NOTIFY_IME_OF_NOTHING);
  1557. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_TEXT_CHANGE;
  1558. IMEStateManager::NotifyIME(notification, mIMEContentObserver->mWidget);
  1559. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_NOTHING;
  1560. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1561. ("0x%p IMEContentObserver::IMENotificationSender::"
  1562. "SendTextChange(), sent NOTIFY_IME_OF_TEXT_CHANGE", this));
  1563. }
  1564. void
  1565. IMEContentObserver::IMENotificationSender::SendPositionChange()
  1566. {
  1567. if (!CanNotifyIME(eChangeEventType_Position)) {
  1568. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1569. ("0x%p IMEContentObserver::IMENotificationSender::"
  1570. "SendPositionChange(), FAILED, due to impossible to notify IME of "
  1571. "position change", this));
  1572. return;
  1573. }
  1574. if (!IsSafeToNotifyIME(eChangeEventType_Position)) {
  1575. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1576. ("0x%p IMEContentObserver::IMENotificationSender::"
  1577. "SendPositionChange(), retrying to send "
  1578. "NOTIFY_IME_OF_POSITION_CHANGE...", this));
  1579. mIMEContentObserver->PostPositionChangeNotification();
  1580. return;
  1581. }
  1582. MOZ_LOG(sIMECOLog, LogLevel::Info,
  1583. ("0x%p IMEContentObserver::IMENotificationSender::"
  1584. "SendPositionChange(), sending NOTIFY_IME_OF_POSITION_CHANGE...", this));
  1585. MOZ_RELEASE_ASSERT(mIMEContentObserver->mSendingNotification ==
  1586. NOTIFY_IME_OF_NOTHING);
  1587. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_POSITION_CHANGE;
  1588. IMEStateManager::NotifyIME(IMENotification(NOTIFY_IME_OF_POSITION_CHANGE),
  1589. mIMEContentObserver->mWidget);
  1590. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_NOTHING;
  1591. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1592. ("0x%p IMEContentObserver::IMENotificationSender::"
  1593. "SendPositionChange(), sent NOTIFY_IME_OF_POSITION_CHANGE", this));
  1594. }
  1595. void
  1596. IMEContentObserver::IMENotificationSender::SendCompositionEventHandled()
  1597. {
  1598. if (!CanNotifyIME(eChangeEventType_CompositionEventHandled)) {
  1599. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1600. ("0x%p IMEContentObserver::IMENotificationSender::"
  1601. "SendCompositionEventHandled(), FAILED, due to impossible to notify "
  1602. "IME of composition event handled", this));
  1603. return;
  1604. }
  1605. if (!IsSafeToNotifyIME(eChangeEventType_CompositionEventHandled)) {
  1606. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1607. ("0x%p IMEContentObserver::IMENotificationSender::"
  1608. "SendCompositionEventHandled(), retrying to send "
  1609. "NOTIFY_IME_OF_POSITION_CHANGE...", this));
  1610. mIMEContentObserver->PostCompositionEventHandledNotification();
  1611. return;
  1612. }
  1613. MOZ_LOG(sIMECOLog, LogLevel::Info,
  1614. ("0x%p IMEContentObserver::IMENotificationSender::"
  1615. "SendCompositionEventHandled(), sending "
  1616. "NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED...", this));
  1617. MOZ_RELEASE_ASSERT(mIMEContentObserver->mSendingNotification ==
  1618. NOTIFY_IME_OF_NOTHING);
  1619. mIMEContentObserver->mSendingNotification =
  1620. NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED;
  1621. IMEStateManager::NotifyIME(
  1622. IMENotification(NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED),
  1623. mIMEContentObserver->mWidget);
  1624. mIMEContentObserver->mSendingNotification = NOTIFY_IME_OF_NOTHING;
  1625. MOZ_LOG(sIMECOLog, LogLevel::Debug,
  1626. ("0x%p IMEContentObserver::IMENotificationSender::"
  1627. "SendCompositionEventHandled(), sent "
  1628. "NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED", this));
  1629. }
  1630. } // namespace mozilla