IMEStateManager.cpp 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790
  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 "mozilla/IMEStateManager.h"
  7. #include "mozilla/Attributes.h"
  8. #include "mozilla/EditorBase.h"
  9. #include "mozilla/EventListenerManager.h"
  10. #include "mozilla/EventStates.h"
  11. #include "mozilla/MouseEvents.h"
  12. #include "mozilla/Preferences.h"
  13. #include "mozilla/Services.h"
  14. #include "mozilla/TextComposition.h"
  15. #include "mozilla/TextEvents.h"
  16. #include "mozilla/Unused.h"
  17. #include "mozilla/dom/Event.h"
  18. #include "mozilla/dom/HTMLFormElement.h"
  19. #include "mozilla/dom/TabParent.h"
  20. #include "HTMLInputElement.h"
  21. #include "IMEContentObserver.h"
  22. #include "nsCOMPtr.h"
  23. #include "nsContentUtils.h"
  24. #include "nsIContent.h"
  25. #include "nsIDocument.h"
  26. #include "nsIDOMMouseEvent.h"
  27. #include "nsIForm.h"
  28. #include "nsIFormControl.h"
  29. #include "nsINode.h"
  30. #include "nsIObserverService.h"
  31. #include "nsIPresShell.h"
  32. #include "nsISelection.h"
  33. #include "nsISupports.h"
  34. #include "nsPresContext.h"
  35. namespace mozilla {
  36. using namespace dom;
  37. using namespace widget;
  38. /**
  39. * When a method is called, log its arguments and/or related static variables
  40. * with LogLevel::Info. However, if it puts too many logs like
  41. * OnDestroyPresContext(), should long only when the method actually does
  42. * something. In this case, the log should start with "<method name>".
  43. *
  44. * When a method quits due to unexpected situation, log the reason with
  45. * LogLevel::Error. In this case, the log should start with
  46. * "<method name>(), FAILED". The indent makes the log look easier.
  47. *
  48. * When a method does something only in some situations and it may be important
  49. * for debug, log the information with LogLevel::Debug. In this case, the log
  50. * should start with " <method name>(),".
  51. */
  52. LazyLogModule sISMLog("IMEStateManager");
  53. static const char*
  54. GetBoolName(bool aBool)
  55. {
  56. return aBool ? "true" : "false";
  57. }
  58. static const char*
  59. GetActionCauseName(InputContextAction::Cause aCause)
  60. {
  61. switch (aCause) {
  62. case InputContextAction::CAUSE_UNKNOWN:
  63. return "CAUSE_UNKNOWN";
  64. case InputContextAction::CAUSE_UNKNOWN_CHROME:
  65. return "CAUSE_UNKNOWN_CHROME";
  66. case InputContextAction::CAUSE_KEY:
  67. return "CAUSE_KEY";
  68. case InputContextAction::CAUSE_MOUSE:
  69. return "CAUSE_MOUSE";
  70. case InputContextAction::CAUSE_TOUCH:
  71. return "CAUSE_TOUCH";
  72. default:
  73. return "illegal value";
  74. }
  75. }
  76. static const char*
  77. GetActionFocusChangeName(InputContextAction::FocusChange aFocusChange)
  78. {
  79. switch (aFocusChange) {
  80. case InputContextAction::FOCUS_NOT_CHANGED:
  81. return "FOCUS_NOT_CHANGED";
  82. case InputContextAction::GOT_FOCUS:
  83. return "GOT_FOCUS";
  84. case InputContextAction::LOST_FOCUS:
  85. return "LOST_FOCUS";
  86. case InputContextAction::MENU_GOT_PSEUDO_FOCUS:
  87. return "MENU_GOT_PSEUDO_FOCUS";
  88. case InputContextAction::MENU_LOST_PSEUDO_FOCUS:
  89. return "MENU_LOST_PSEUDO_FOCUS";
  90. default:
  91. return "illegal value";
  92. }
  93. }
  94. static const char*
  95. GetIMEStateEnabledName(IMEState::Enabled aEnabled)
  96. {
  97. switch (aEnabled) {
  98. case IMEState::DISABLED:
  99. return "DISABLED";
  100. case IMEState::ENABLED:
  101. return "ENABLED";
  102. case IMEState::PASSWORD:
  103. return "PASSWORD";
  104. case IMEState::PLUGIN:
  105. return "PLUGIN";
  106. default:
  107. return "illegal value";
  108. }
  109. }
  110. static const char*
  111. GetIMEStateSetOpenName(IMEState::Open aOpen)
  112. {
  113. switch (aOpen) {
  114. case IMEState::DONT_CHANGE_OPEN_STATE:
  115. return "DONT_CHANGE_OPEN_STATE";
  116. case IMEState::OPEN:
  117. return "OPEN";
  118. case IMEState::CLOSED:
  119. return "CLOSED";
  120. default:
  121. return "illegal value";
  122. }
  123. }
  124. StaticRefPtr<nsIContent> IMEStateManager::sContent;
  125. StaticRefPtr<nsPresContext> IMEStateManager::sPresContext;
  126. nsIWidget* IMEStateManager::sWidget = nullptr;
  127. nsIWidget* IMEStateManager::sFocusedIMEWidget = nullptr;
  128. nsIWidget* IMEStateManager::sActiveInputContextWidget = nullptr;
  129. StaticRefPtr<TabParent> IMEStateManager::sActiveTabParent;
  130. StaticRefPtr<IMEContentObserver> IMEStateManager::sActiveIMEContentObserver;
  131. TextCompositionArray* IMEStateManager::sTextCompositions = nullptr;
  132. bool IMEStateManager::sInstalledMenuKeyboardListener = false;
  133. bool IMEStateManager::sIsGettingNewIMEState = false;
  134. bool IMEStateManager::sCheckForIMEUnawareWebApps = false;
  135. bool IMEStateManager::sRemoteHasFocus = false;
  136. // static
  137. void
  138. IMEStateManager::Init()
  139. {
  140. Preferences::AddBoolVarCache(
  141. &sCheckForIMEUnawareWebApps,
  142. "intl.ime.hack.on_ime_unaware_apps.fire_key_events_for_composition",
  143. false);
  144. }
  145. // static
  146. void
  147. IMEStateManager::Shutdown()
  148. {
  149. MOZ_LOG(sISMLog, LogLevel::Info,
  150. ("Shutdown(), sTextCompositions=0x%p, sTextCompositions->Length()=%u",
  151. sTextCompositions, sTextCompositions ? sTextCompositions->Length() : 0));
  152. MOZ_ASSERT(!sTextCompositions || !sTextCompositions->Length());
  153. delete sTextCompositions;
  154. sTextCompositions = nullptr;
  155. }
  156. // static
  157. void
  158. IMEStateManager::OnTabParentDestroying(TabParent* aTabParent)
  159. {
  160. if (sActiveTabParent != aTabParent) {
  161. return;
  162. }
  163. MOZ_LOG(sISMLog, LogLevel::Info,
  164. ("OnTabParentDestroying(aTabParent=0x%p), "
  165. "The active TabParent is being destroyed", aTabParent));
  166. // The active remote process might have crashed.
  167. sActiveTabParent = nullptr;
  168. // TODO: Need to cancel composition without TextComposition and make
  169. // disable IME.
  170. }
  171. // static
  172. void
  173. IMEStateManager::WidgetDestroyed(nsIWidget* aWidget)
  174. {
  175. if (sWidget == aWidget) {
  176. sWidget = nullptr;
  177. }
  178. if (sFocusedIMEWidget == aWidget) {
  179. sFocusedIMEWidget = nullptr;
  180. }
  181. if (sActiveInputContextWidget == aWidget) {
  182. sActiveInputContextWidget = nullptr;
  183. }
  184. }
  185. // static
  186. void
  187. IMEStateManager::StopIMEStateManagement()
  188. {
  189. MOZ_LOG(sISMLog, LogLevel::Info,
  190. ("StopIMEStateManagement()"));
  191. // NOTE: Don't set input context from here since this has already lost
  192. // the rights to change input context.
  193. if (sTextCompositions && sPresContext) {
  194. NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, sPresContext);
  195. }
  196. sActiveInputContextWidget = nullptr;
  197. sPresContext = nullptr;
  198. sContent = nullptr;
  199. sActiveTabParent = nullptr;
  200. DestroyIMEContentObserver();
  201. }
  202. // static
  203. void
  204. IMEStateManager::MaybeStartOffsetUpdatedInChild(nsIWidget* aWidget,
  205. uint32_t aStartOffset)
  206. {
  207. if (NS_WARN_IF(!sTextCompositions)) {
  208. MOZ_LOG(sISMLog, LogLevel::Warning,
  209. ("MaybeStartOffsetUpdatedInChild(aWidget=0x%p, aStartOffset=%u), "
  210. "called when there is no composition", aWidget, aStartOffset));
  211. return;
  212. }
  213. RefPtr<TextComposition> composition = GetTextCompositionFor(aWidget);
  214. if (NS_WARN_IF(!composition)) {
  215. MOZ_LOG(sISMLog, LogLevel::Warning,
  216. ("MaybeStartOffsetUpdatedInChild(aWidget=0x%p, aStartOffset=%u), "
  217. "called when there is no composition", aWidget, aStartOffset));
  218. return;
  219. }
  220. if (composition->NativeOffsetOfStartComposition() == aStartOffset) {
  221. return;
  222. }
  223. MOZ_LOG(sISMLog, LogLevel::Info,
  224. ("MaybeStartOffsetUpdatedInChild(aWidget=0x%p, aStartOffset=%u), "
  225. "old offset=%u",
  226. aWidget, aStartOffset, composition->NativeOffsetOfStartComposition()));
  227. composition->OnStartOffsetUpdatedInChild(aStartOffset);
  228. }
  229. // static
  230. nsresult
  231. IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
  232. {
  233. NS_ENSURE_ARG_POINTER(aPresContext);
  234. // First, if there is a composition in the aPresContext, clean up it.
  235. if (sTextCompositions) {
  236. TextCompositionArray::index_type i =
  237. sTextCompositions->IndexOf(aPresContext);
  238. if (i != TextCompositionArray::NoIndex) {
  239. MOZ_LOG(sISMLog, LogLevel::Debug,
  240. (" OnDestroyPresContext(), "
  241. "removing TextComposition instance from the array (index=%u)", i));
  242. // there should be only one composition per presContext object.
  243. sTextCompositions->ElementAt(i)->Destroy();
  244. sTextCompositions->RemoveElementAt(i);
  245. if (sTextCompositions->IndexOf(aPresContext) !=
  246. TextCompositionArray::NoIndex) {
  247. MOZ_LOG(sISMLog, LogLevel::Error,
  248. (" OnDestroyPresContext(), FAILED to remove "
  249. "TextComposition instance from the array"));
  250. MOZ_CRASH("Failed to remove TextComposition instance from the array");
  251. }
  252. }
  253. }
  254. if (aPresContext != sPresContext) {
  255. return NS_OK;
  256. }
  257. MOZ_LOG(sISMLog, LogLevel::Info,
  258. ("OnDestroyPresContext(aPresContext=0x%p), "
  259. "sPresContext=0x%p, sContent=0x%p, sTextCompositions=0x%p",
  260. aPresContext, sPresContext.get(), sContent.get(), sTextCompositions));
  261. DestroyIMEContentObserver();
  262. if (sWidget) {
  263. IMEState newState = GetNewIMEState(sPresContext, nullptr);
  264. InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
  265. InputContextAction::LOST_FOCUS);
  266. SetIMEState(newState, nullptr, nullptr, sWidget, action);
  267. }
  268. sWidget = nullptr;
  269. sContent = nullptr;
  270. sPresContext = nullptr;
  271. sActiveTabParent = nullptr;
  272. return NS_OK;
  273. }
  274. // static
  275. nsresult
  276. IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
  277. nsIContent* aContent)
  278. {
  279. NS_ENSURE_ARG_POINTER(aPresContext);
  280. // First, if there is a composition in the aContent, clean up it.
  281. if (sTextCompositions) {
  282. RefPtr<TextComposition> compositionInContent =
  283. sTextCompositions->GetCompositionInContent(aPresContext, aContent);
  284. if (compositionInContent) {
  285. MOZ_LOG(sISMLog, LogLevel::Debug,
  286. (" OnRemoveContent(), "
  287. "composition is in the content"));
  288. // Try resetting the native IME state. Be aware, typically, this method
  289. // is called during the content being removed. Then, the native
  290. // composition events which are caused by following APIs are ignored due
  291. // to unsafe to run script (in PresShell::HandleEvent()).
  292. nsresult rv =
  293. compositionInContent->NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
  294. if (NS_FAILED(rv)) {
  295. compositionInContent->NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
  296. }
  297. }
  298. }
  299. if (!sPresContext || !sContent ||
  300. !nsContentUtils::ContentIsDescendantOf(sContent, aContent)) {
  301. return NS_OK;
  302. }
  303. MOZ_LOG(sISMLog, LogLevel::Info,
  304. ("OnRemoveContent(aPresContext=0x%p, aContent=0x%p), "
  305. "sPresContext=0x%p, sContent=0x%p, sTextCompositions=0x%p",
  306. aPresContext, aContent, sPresContext.get(), sContent.get(), sTextCompositions));
  307. DestroyIMEContentObserver();
  308. // Current IME transaction should commit
  309. if (sWidget) {
  310. IMEState newState = GetNewIMEState(sPresContext, nullptr);
  311. InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
  312. InputContextAction::LOST_FOCUS);
  313. SetIMEState(newState, aPresContext, nullptr, sWidget, action);
  314. }
  315. sWidget = nullptr;
  316. sContent = nullptr;
  317. sPresContext = nullptr;
  318. sActiveTabParent = nullptr;
  319. return NS_OK;
  320. }
  321. // static
  322. bool
  323. IMEStateManager::CanHandleWith(nsPresContext* aPresContext)
  324. {
  325. return aPresContext &&
  326. aPresContext->GetPresShell() &&
  327. !aPresContext->PresShell()->IsDestroying();
  328. }
  329. // static
  330. nsresult
  331. IMEStateManager::OnChangeFocus(nsPresContext* aPresContext,
  332. nsIContent* aContent,
  333. InputContextAction::Cause aCause)
  334. {
  335. MOZ_LOG(sISMLog, LogLevel::Info,
  336. ("OnChangeFocus(aPresContext=0x%p, aContent=0x%p, aCause=%s)",
  337. aPresContext, aContent, GetActionCauseName(aCause)));
  338. InputContextAction action(aCause);
  339. return OnChangeFocusInternal(aPresContext, aContent, action);
  340. }
  341. // static
  342. nsresult
  343. IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
  344. nsIContent* aContent,
  345. InputContextAction aAction)
  346. {
  347. RefPtr<TabParent> newTabParent = TabParent::GetFrom(aContent);
  348. MOZ_LOG(sISMLog, LogLevel::Info,
  349. ("OnChangeFocusInternal(aPresContext=0x%p (available: %s), "
  350. "aContent=0x%p (TabParent=0x%p), aAction={ mCause=%s, mFocusChange=%s }), "
  351. "sPresContext=0x%p (available: %s), sContent=0x%p, "
  352. "sWidget=0x%p (available: %s), sActiveTabParent=0x%p, "
  353. "sActiveIMEContentObserver=0x%p, sInstalledMenuKeyboardListener=%s",
  354. aPresContext, GetBoolName(CanHandleWith(aPresContext)), aContent,
  355. newTabParent.get(), GetActionCauseName(aAction.mCause),
  356. GetActionFocusChangeName(aAction.mFocusChange),
  357. sPresContext.get(), GetBoolName(CanHandleWith(sPresContext)),
  358. sContent.get(), sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
  359. sActiveTabParent.get(), sActiveIMEContentObserver.get(),
  360. GetBoolName(sInstalledMenuKeyboardListener)));
  361. // If new aPresShell has been destroyed, this should handle the focus change
  362. // as nobody is getting focus.
  363. if (NS_WARN_IF(aPresContext && !CanHandleWith(aPresContext))) {
  364. MOZ_LOG(sISMLog, LogLevel::Warning,
  365. (" OnChangeFocusInternal(), called with destroyed PresShell, "
  366. "handling this call as nobody getting focus"));
  367. aPresContext = nullptr;
  368. aContent = nullptr;
  369. }
  370. nsCOMPtr<nsIWidget> oldWidget = sWidget;
  371. nsCOMPtr<nsIWidget> newWidget =
  372. aPresContext ? aPresContext->GetRootWidget() : nullptr;
  373. bool focusActuallyChanging =
  374. (sContent != aContent || sPresContext != aPresContext ||
  375. oldWidget != newWidget || sActiveTabParent != newTabParent);
  376. if (oldWidget && focusActuallyChanging) {
  377. // If we're deactivating, we shouldn't commit composition forcibly because
  378. // the user may want to continue the composition.
  379. if (aPresContext) {
  380. NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
  381. }
  382. }
  383. if (sActiveIMEContentObserver &&
  384. (aPresContext || !sActiveIMEContentObserver->KeepAliveDuringDeactive()) &&
  385. !sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
  386. DestroyIMEContentObserver();
  387. }
  388. if (!aPresContext) {
  389. MOZ_LOG(sISMLog, LogLevel::Debug,
  390. (" OnChangeFocusInternal(), "
  391. "no nsPresContext is being activated"));
  392. return NS_OK;
  393. }
  394. nsIContentParent* currentContentParent =
  395. sActiveTabParent ? sActiveTabParent->Manager() : nullptr;
  396. nsIContentParent* newContentParent =
  397. newTabParent ? newTabParent->Manager() : nullptr;
  398. if (sActiveTabParent && currentContentParent != newContentParent) {
  399. MOZ_LOG(sISMLog, LogLevel::Debug,
  400. (" OnChangeFocusInternal(), notifying previous "
  401. "focused child process of parent process or another child process "
  402. "getting focus"));
  403. Unused << sActiveTabParent->SendStopIMEStateManagement();
  404. }
  405. if (NS_WARN_IF(!newWidget)) {
  406. MOZ_LOG(sISMLog, LogLevel::Error,
  407. (" OnChangeFocusInternal(), FAILED due to "
  408. "no widget to manage its IME state"));
  409. return NS_OK;
  410. }
  411. // Update the cached widget since root view of the presContext may be
  412. // changed to different view.
  413. sWidget = newWidget;
  414. // If a child process has focus, we should disable IME state until the child
  415. // process actually gets focus because if user types keys before that they
  416. // are handled by IME.
  417. IMEState newState =
  418. newTabParent ? IMEState(IMEState::DISABLED) :
  419. GetNewIMEState(aPresContext, aContent);
  420. bool setIMEState = true;
  421. if (newTabParent) {
  422. if (aAction.mFocusChange == InputContextAction::MENU_GOT_PSEUDO_FOCUS ||
  423. aAction.mFocusChange == InputContextAction::MENU_LOST_PSEUDO_FOCUS) {
  424. // XXX When menu keyboard listener is being uninstalled, IME state needs
  425. // to be restored by the child process asynchronously. Therefore,
  426. // some key events which are fired immediately after closing menu
  427. // may not be handled by IME.
  428. Unused << newTabParent->
  429. SendMenuKeyboardListenerInstalled(sInstalledMenuKeyboardListener);
  430. setIMEState = sInstalledMenuKeyboardListener;
  431. } else if (focusActuallyChanging) {
  432. InputContext context = newWidget->GetInputContext();
  433. if (context.mIMEState.mEnabled == IMEState::DISABLED) {
  434. setIMEState = false;
  435. MOZ_LOG(sISMLog, LogLevel::Debug,
  436. (" OnChangeFocusInternal(), doesn't set IME "
  437. "state because focused element (or document) is in a child process "
  438. "and the IME state is already disabled"));
  439. } else {
  440. MOZ_LOG(sISMLog, LogLevel::Debug,
  441. (" OnChangeFocusInternal(), will disable IME "
  442. "until new focused element (or document) in the child process "
  443. "will get focus actually"));
  444. }
  445. } else {
  446. // When focus is NOT changed actually, we shouldn't set IME state since
  447. // that means that the window is being activated and the child process
  448. // may have composition. Then, we shouldn't commit the composition with
  449. // making IME state disabled.
  450. setIMEState = false;
  451. MOZ_LOG(sISMLog, LogLevel::Debug,
  452. (" OnChangeFocusInternal(), doesn't set IME "
  453. "state because focused element (or document) is already in the child "
  454. "process"));
  455. }
  456. }
  457. if (setIMEState) {
  458. if (!focusActuallyChanging) {
  459. // actual focus isn't changing, but if IME enabled state is changing,
  460. // we should do it.
  461. InputContext context = newWidget->GetInputContext();
  462. if (context.mIMEState.mEnabled == newState.mEnabled) {
  463. MOZ_LOG(sISMLog, LogLevel::Debug,
  464. (" OnChangeFocusInternal(), "
  465. "neither focus nor IME state is changing"));
  466. return NS_OK;
  467. }
  468. aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED;
  469. // Even if focus isn't changing actually, we should commit current
  470. // composition here since the IME state is changing.
  471. if (sPresContext && oldWidget && !focusActuallyChanging) {
  472. NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
  473. }
  474. } else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
  475. // If aContent isn't null or aContent is null but editable, somebody gets
  476. // focus.
  477. bool gotFocus = aContent || (newState.mEnabled == IMEState::ENABLED);
  478. aAction.mFocusChange =
  479. gotFocus ? InputContextAction::GOT_FOCUS :
  480. InputContextAction::LOST_FOCUS;
  481. }
  482. // Update IME state for new focus widget
  483. SetIMEState(newState, aPresContext, aContent, newWidget, aAction);
  484. }
  485. sActiveTabParent = newTabParent;
  486. sPresContext = aPresContext;
  487. sContent = aContent;
  488. // Don't call CreateIMEContentObserver() here except when a plugin gets
  489. // focus because it will be called from the focus event handler of focused
  490. // editor.
  491. if (newState.mEnabled == IMEState::PLUGIN) {
  492. CreateIMEContentObserver(nullptr);
  493. if (sActiveIMEContentObserver) {
  494. MOZ_LOG(sISMLog, LogLevel::Debug,
  495. (" OnChangeFocusInternal(), an "
  496. "IMEContentObserver instance is created for plugin and trying to "
  497. "flush its pending notifications..."));
  498. sActiveIMEContentObserver->TryToFlushPendingNotifications();
  499. }
  500. }
  501. return NS_OK;
  502. }
  503. // static
  504. void
  505. IMEStateManager::OnInstalledMenuKeyboardListener(bool aInstalling)
  506. {
  507. MOZ_LOG(sISMLog, LogLevel::Info,
  508. ("OnInstalledMenuKeyboardListener(aInstalling=%s), "
  509. "sInstalledMenuKeyboardListener=%s",
  510. GetBoolName(aInstalling), GetBoolName(sInstalledMenuKeyboardListener)));
  511. sInstalledMenuKeyboardListener = aInstalling;
  512. InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
  513. aInstalling ? InputContextAction::MENU_GOT_PSEUDO_FOCUS :
  514. InputContextAction::MENU_LOST_PSEUDO_FOCUS);
  515. OnChangeFocusInternal(sPresContext, sContent, action);
  516. }
  517. // static
  518. bool
  519. IMEStateManager::OnMouseButtonEventInEditor(nsPresContext* aPresContext,
  520. nsIContent* aContent,
  521. nsIDOMMouseEvent* aMouseEvent)
  522. {
  523. MOZ_LOG(sISMLog, LogLevel::Info,
  524. ("OnMouseButtonEventInEditor(aPresContext=0x%p, "
  525. "aContent=0x%p, aMouseEvent=0x%p), sPresContext=0x%p, sContent=0x%p",
  526. aPresContext, aContent, aMouseEvent, sPresContext.get(), sContent.get()));
  527. if (sPresContext != aPresContext || sContent != aContent) {
  528. MOZ_LOG(sISMLog, LogLevel::Debug,
  529. (" OnMouseButtonEventInEditor(), "
  530. "the mouse event isn't fired on the editor managed by ISM"));
  531. return false;
  532. }
  533. if (!sActiveIMEContentObserver) {
  534. MOZ_LOG(sISMLog, LogLevel::Debug,
  535. (" OnMouseButtonEventInEditor(), "
  536. "there is no active IMEContentObserver"));
  537. return false;
  538. }
  539. if (!sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
  540. MOZ_LOG(sISMLog, LogLevel::Debug,
  541. (" OnMouseButtonEventInEditor(), "
  542. "the active IMEContentObserver isn't managing the editor"));
  543. return false;
  544. }
  545. WidgetMouseEvent* internalEvent =
  546. aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
  547. if (NS_WARN_IF(!internalEvent)) {
  548. MOZ_LOG(sISMLog, LogLevel::Debug,
  549. (" OnMouseButtonEventInEditor(), "
  550. "the internal event of aMouseEvent isn't WidgetMouseEvent"));
  551. return false;
  552. }
  553. bool consumed =
  554. sActiveIMEContentObserver->OnMouseButtonEvent(aPresContext, internalEvent);
  555. if (MOZ_LOG_TEST(sISMLog, LogLevel::Info)) {
  556. nsAutoString eventType;
  557. aMouseEvent->AsEvent()->GetType(eventType);
  558. MOZ_LOG(sISMLog, LogLevel::Info,
  559. (" OnMouseButtonEventInEditor(), "
  560. "mouse event (type=%s, button=%d) is %s",
  561. NS_ConvertUTF16toUTF8(eventType).get(), internalEvent->button,
  562. consumed ? "consumed" : "not consumed"));
  563. }
  564. return consumed;
  565. }
  566. // static
  567. void
  568. IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
  569. nsIContent* aContent,
  570. nsIDOMMouseEvent* aMouseEvent)
  571. {
  572. MOZ_LOG(sISMLog, LogLevel::Info,
  573. ("OnClickInEditor(aPresContext=0x%p, aContent=0x%p, aMouseEvent=0x%p), "
  574. "sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s)",
  575. aPresContext, aContent, aMouseEvent, sPresContext.get(), sContent.get(),
  576. sWidget, GetBoolName(sWidget && !sWidget->Destroyed())));
  577. if (sPresContext != aPresContext || sContent != aContent ||
  578. NS_WARN_IF(!sPresContext) || NS_WARN_IF(!sWidget) ||
  579. NS_WARN_IF(sWidget->Destroyed())) {
  580. MOZ_LOG(sISMLog, LogLevel::Debug,
  581. (" OnClickInEditor(), "
  582. "the mouse event isn't fired on the editor managed by ISM"));
  583. return;
  584. }
  585. nsCOMPtr<nsIWidget> widget(sWidget);
  586. MOZ_ASSERT(!sPresContext->GetRootWidget() ||
  587. sPresContext->GetRootWidget() == widget);
  588. bool isTrusted;
  589. nsresult rv = aMouseEvent->AsEvent()->GetIsTrusted(&isTrusted);
  590. NS_ENSURE_SUCCESS_VOID(rv);
  591. if (!isTrusted) {
  592. MOZ_LOG(sISMLog, LogLevel::Debug,
  593. (" OnClickInEditor(), "
  594. "the mouse event isn't a trusted event"));
  595. return; // ignore untrusted event.
  596. }
  597. int16_t button;
  598. rv = aMouseEvent->GetButton(&button);
  599. NS_ENSURE_SUCCESS_VOID(rv);
  600. if (button != 0) {
  601. MOZ_LOG(sISMLog, LogLevel::Debug,
  602. (" OnClickInEditor(), "
  603. "the mouse event isn't a left mouse button event"));
  604. return; // not a left click event.
  605. }
  606. int32_t clickCount;
  607. rv = aMouseEvent->GetDetail(&clickCount);
  608. NS_ENSURE_SUCCESS_VOID(rv);
  609. if (clickCount != 1) {
  610. MOZ_LOG(sISMLog, LogLevel::Debug,
  611. (" OnClickInEditor(), "
  612. "the mouse event isn't a single click event"));
  613. return; // should notify only first click event.
  614. }
  615. uint16_t inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
  616. aMouseEvent->GetMozInputSource(&inputSource);
  617. InputContextAction::Cause cause =
  618. inputSource == nsIDOMMouseEvent::MOZ_SOURCE_TOUCH ?
  619. InputContextAction::CAUSE_TOUCH : InputContextAction::CAUSE_MOUSE;
  620. InputContextAction action(cause, InputContextAction::FOCUS_NOT_CHANGED);
  621. IMEState newState = GetNewIMEState(aPresContext, aContent);
  622. SetIMEState(newState, aPresContext, aContent, widget, action);
  623. }
  624. // static
  625. void
  626. IMEStateManager::OnFocusInEditor(nsPresContext* aPresContext,
  627. nsIContent* aContent,
  628. nsIEditor* aEditor)
  629. {
  630. MOZ_LOG(sISMLog, LogLevel::Info,
  631. ("OnFocusInEditor(aPresContext=0x%p, aContent=0x%p, aEditor=0x%p), "
  632. "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p",
  633. aPresContext, aContent, aEditor, sPresContext.get(), sContent.get(),
  634. sActiveIMEContentObserver.get()));
  635. if (sPresContext != aPresContext || sContent != aContent) {
  636. MOZ_LOG(sISMLog, LogLevel::Debug,
  637. (" OnFocusInEditor(), "
  638. "an editor not managed by ISM gets focus"));
  639. return;
  640. }
  641. // If the IMEContentObserver instance isn't managing the editor actually,
  642. // we need to recreate the instance.
  643. if (sActiveIMEContentObserver) {
  644. if (sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
  645. MOZ_LOG(sISMLog, LogLevel::Debug,
  646. (" OnFocusInEditor(), "
  647. "the editor is already being managed by sActiveIMEContentObserver"));
  648. return;
  649. }
  650. DestroyIMEContentObserver();
  651. }
  652. CreateIMEContentObserver(aEditor);
  653. // Let's flush the focus notification now.
  654. if (sActiveIMEContentObserver) {
  655. MOZ_LOG(sISMLog, LogLevel::Debug,
  656. (" OnFocusInEditor(), new IMEContentObserver is "
  657. "created, trying to flush pending notifications..."));
  658. sActiveIMEContentObserver->TryToFlushPendingNotifications();
  659. }
  660. }
  661. // static
  662. void
  663. IMEStateManager::OnEditorInitialized(nsIEditor* aEditor)
  664. {
  665. if (!sActiveIMEContentObserver ||
  666. sActiveIMEContentObserver->GetEditor() != aEditor) {
  667. return;
  668. }
  669. MOZ_LOG(sISMLog, LogLevel::Info,
  670. ("OnEditorInitialized(aEditor=0x%p)",
  671. aEditor));
  672. sActiveIMEContentObserver->UnsuppressNotifyingIME();
  673. }
  674. // static
  675. void
  676. IMEStateManager::OnEditorDestroying(nsIEditor* aEditor)
  677. {
  678. if (!sActiveIMEContentObserver ||
  679. sActiveIMEContentObserver->GetEditor() != aEditor) {
  680. return;
  681. }
  682. MOZ_LOG(sISMLog, LogLevel::Info,
  683. ("OnEditorDestroying(aEditor=0x%p)",
  684. aEditor));
  685. // The IMEContentObserver shouldn't notify IME of anything until reframing
  686. // is finished.
  687. sActiveIMEContentObserver->SuppressNotifyingIME();
  688. }
  689. // static
  690. void
  691. IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
  692. nsIContent* aContent,
  693. EditorBase& aEditorBase)
  694. {
  695. MOZ_LOG(sISMLog, LogLevel::Info,
  696. ("UpdateIMEState(aNewIMEState={ mEnabled=%s, "
  697. "mOpen=%s }, aContent=0x%p, aEditorBase=0x%p), "
  698. "sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s), "
  699. "sActiveIMEContentObserver=0x%p, sIsGettingNewIMEState=%s",
  700. GetIMEStateEnabledName(aNewIMEState.mEnabled),
  701. GetIMEStateSetOpenName(aNewIMEState.mOpen), aContent, &aEditorBase,
  702. sPresContext.get(), sContent.get(),
  703. sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
  704. sActiveIMEContentObserver.get(),
  705. GetBoolName(sIsGettingNewIMEState)));
  706. if (sIsGettingNewIMEState) {
  707. MOZ_LOG(sISMLog, LogLevel::Debug,
  708. (" UpdateIMEState(), "
  709. "does nothing because of called while getting new IME state"));
  710. return;
  711. }
  712. nsCOMPtr<nsIPresShell> presShell = aEditorBase.GetPresShell();
  713. if (NS_WARN_IF(!presShell)) {
  714. MOZ_LOG(sISMLog, LogLevel::Error,
  715. (" UpdateIMEState(), FAILED due to "
  716. "editor doesn't have PresShell"));
  717. return;
  718. }
  719. nsPresContext* presContext = presShell->GetPresContext();
  720. if (NS_WARN_IF(!presContext)) {
  721. MOZ_LOG(sISMLog, LogLevel::Error,
  722. (" UpdateIMEState(), FAILED due to "
  723. "editor doesn't have PresContext"));
  724. return;
  725. }
  726. // IMEStateManager::UpdateIMEState() should be called after
  727. // IMEStateManager::OnChangeFocus() is called for setting focus to aContent
  728. // and aEditorBase. However, when aEditorBase is an HTMLEditor, this may be
  729. // called by nsIEditor::PostCreate() before IMEStateManager::OnChangeFocus().
  730. // Similarly, when aEditorBase is a TextEditor, this may be called by
  731. // nsIEditor::SetFlags(). In such cases, this method should do nothing
  732. // because input context should be updated when
  733. // IMEStateManager::OnChangeFocus() is called later.
  734. if (sPresContext != presContext) {
  735. MOZ_LOG(sISMLog, LogLevel::Warning,
  736. (" UpdateIMEState(), does nothing due to "
  737. "the editor hasn't managed by IMEStateManager yet"));
  738. return;
  739. }
  740. // If IMEStateManager doesn't manage any document, this cannot update IME
  741. // state of any widget.
  742. if (NS_WARN_IF(!sPresContext)) {
  743. MOZ_LOG(sISMLog, LogLevel::Error,
  744. (" UpdateIMEState(), FAILED due to "
  745. "no managing nsPresContext"));
  746. return;
  747. }
  748. if (NS_WARN_IF(!sWidget) || NS_WARN_IF(sWidget->Destroyed())) {
  749. MOZ_LOG(sISMLog, LogLevel::Error,
  750. (" UpdateIMEState(), FAILED due to "
  751. "the widget for the managing nsPresContext has gone"));
  752. return;
  753. }
  754. nsCOMPtr<nsIWidget> widget(sWidget);
  755. MOZ_ASSERT(!sPresContext->GetRootWidget() ||
  756. sPresContext->GetRootWidget() == widget);
  757. // Even if there is active IMEContentObserver, it may not be observing the
  758. // editor with current editable root content due to reframed. In such case,
  759. // We should try to reinitialize the IMEContentObserver.
  760. if (sActiveIMEContentObserver && IsIMEObserverNeeded(aNewIMEState)) {
  761. MOZ_LOG(sISMLog, LogLevel::Debug,
  762. (" UpdateIMEState(), try to reinitialize the "
  763. "active IMEContentObserver"));
  764. if (!sActiveIMEContentObserver->MaybeReinitialize(widget, sPresContext,
  765. aContent, &aEditorBase)) {
  766. MOZ_LOG(sISMLog, LogLevel::Error,
  767. (" UpdateIMEState(), failed to reinitialize the "
  768. "active IMEContentObserver"));
  769. }
  770. if (NS_WARN_IF(widget->Destroyed())) {
  771. MOZ_LOG(sISMLog, LogLevel::Error,
  772. (" UpdateIMEState(), widget has gone during reinitializing the "
  773. "active IMEContentObserver"));
  774. return;
  775. }
  776. }
  777. // If there is no active IMEContentObserver or it isn't observing the
  778. // editor correctly, we should recreate it.
  779. bool createTextStateManager =
  780. (!sActiveIMEContentObserver ||
  781. !sActiveIMEContentObserver->IsManaging(sPresContext, aContent));
  782. bool updateIMEState =
  783. (widget->GetInputContext().mIMEState.mEnabled != aNewIMEState.mEnabled);
  784. if (NS_WARN_IF(widget->Destroyed())) {
  785. MOZ_LOG(sISMLog, LogLevel::Error,
  786. (" UpdateIMEState(), widget has gone during getting input context"));
  787. return;
  788. }
  789. if (updateIMEState) {
  790. // commit current composition before modifying IME state.
  791. NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget);
  792. if (NS_WARN_IF(widget->Destroyed())) {
  793. MOZ_LOG(sISMLog, LogLevel::Error,
  794. (" UpdateIMEState(), widget has gone during committing composition"));
  795. return;
  796. }
  797. }
  798. if (createTextStateManager) {
  799. DestroyIMEContentObserver();
  800. }
  801. if (updateIMEState) {
  802. InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
  803. InputContextAction::FOCUS_NOT_CHANGED);
  804. SetIMEState(aNewIMEState, sPresContext, aContent, widget, action);
  805. if (NS_WARN_IF(widget->Destroyed())) {
  806. MOZ_LOG(sISMLog, LogLevel::Error,
  807. (" UpdateIMEState(), widget has gone during setting input context"));
  808. return;
  809. }
  810. }
  811. if (createTextStateManager) {
  812. // XXX In this case, it might not be enough safe to notify IME of anything.
  813. // So, don't try to flush pending notifications of IMEContentObserver
  814. // here.
  815. CreateIMEContentObserver(&aEditorBase);
  816. }
  817. }
  818. // static
  819. IMEState
  820. IMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
  821. nsIContent* aContent)
  822. {
  823. MOZ_LOG(sISMLog, LogLevel::Info,
  824. ("GetNewIMEState(aPresContext=0x%p, aContent=0x%p), "
  825. "sInstalledMenuKeyboardListener=%s",
  826. aPresContext, aContent, GetBoolName(sInstalledMenuKeyboardListener)));
  827. if (!CanHandleWith(aPresContext)) {
  828. MOZ_LOG(sISMLog, LogLevel::Debug,
  829. (" GetNewIMEState() returns DISABLED because "
  830. "the nsPresContext has been destroyed"));
  831. return IMEState(IMEState::DISABLED);
  832. }
  833. // On Printing or Print Preview, we don't need IME.
  834. if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
  835. aPresContext->Type() == nsPresContext::eContext_Print) {
  836. MOZ_LOG(sISMLog, LogLevel::Debug,
  837. (" GetNewIMEState() returns DISABLED because "
  838. "the nsPresContext is for print or print preview"));
  839. return IMEState(IMEState::DISABLED);
  840. }
  841. if (sInstalledMenuKeyboardListener) {
  842. MOZ_LOG(sISMLog, LogLevel::Debug,
  843. (" GetNewIMEState() returns DISABLED because "
  844. "menu keyboard listener was installed"));
  845. return IMEState(IMEState::DISABLED);
  846. }
  847. if (!aContent) {
  848. // Even if there are no focused content, the focused document might be
  849. // editable, such case is design mode.
  850. nsIDocument* doc = aPresContext->Document();
  851. if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
  852. MOZ_LOG(sISMLog, LogLevel::Debug,
  853. (" GetNewIMEState() returns ENABLED because "
  854. "design mode editor has focus"));
  855. return IMEState(IMEState::ENABLED);
  856. }
  857. MOZ_LOG(sISMLog, LogLevel::Debug,
  858. (" GetNewIMEState() returns DISABLED because "
  859. "no content has focus"));
  860. return IMEState(IMEState::DISABLED);
  861. }
  862. // nsIContent::GetDesiredIMEState() may cause a call of UpdateIMEState()
  863. // from EditorBase::PostCreate() because GetDesiredIMEState() needs to
  864. // retrieve an editor instance for the element if it's editable element.
  865. // For avoiding such nested IME state updates, we should set
  866. // sIsGettingNewIMEState here and UpdateIMEState() should check it.
  867. GettingNewIMEStateBlocker blocker;
  868. IMEState newIMEState = aContent->GetDesiredIMEState();
  869. MOZ_LOG(sISMLog, LogLevel::Debug,
  870. (" GetNewIMEState() returns { mEnabled=%s, "
  871. "mOpen=%s }",
  872. GetIMEStateEnabledName(newIMEState.mEnabled),
  873. GetIMEStateSetOpenName(newIMEState.mOpen)));
  874. return newIMEState;
  875. }
  876. static bool
  877. MayBeIMEUnawareWebApp(nsINode* aNode)
  878. {
  879. bool haveKeyEventsListener = false;
  880. while (aNode) {
  881. EventListenerManager* const mgr = aNode->GetExistingListenerManager();
  882. if (mgr) {
  883. if (mgr->MayHaveInputOrCompositionEventListener()) {
  884. return false;
  885. }
  886. haveKeyEventsListener |= mgr->MayHaveKeyEventListener();
  887. }
  888. aNode = aNode->GetParentNode();
  889. }
  890. return haveKeyEventsListener;
  891. }
  892. // static
  893. void
  894. IMEStateManager::SetInputContextForChildProcess(
  895. TabParent* aTabParent,
  896. const InputContext& aInputContext,
  897. const InputContextAction& aAction)
  898. {
  899. MOZ_LOG(sISMLog, LogLevel::Info,
  900. ("SetInputContextForChildProcess(aTabParent=0x%p, "
  901. "aInputContext={ mIMEState={ mEnabled=%s, mOpen=%s }, "
  902. "mHTMLInputType=\"%s\", mHTMLInputInputmode=\"%s\", mActionHint=\"%s\", "
  903. "mInPrivateBrowsing=%s }, aAction={ mCause=%s, mAction=%s }), "
  904. "sPresContext=0x%p (available: %s), sWidget=0x%p (available: %s), "
  905. "sActiveTabParent=0x%p",
  906. aTabParent, GetIMEStateEnabledName(aInputContext.mIMEState.mEnabled),
  907. GetIMEStateSetOpenName(aInputContext.mIMEState.mOpen),
  908. NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputType).get(),
  909. NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputInputmode).get(),
  910. NS_ConvertUTF16toUTF8(aInputContext.mActionHint).get(),
  911. GetBoolName(aInputContext.mInPrivateBrowsing),
  912. GetActionCauseName(aAction.mCause),
  913. GetActionFocusChangeName(aAction.mFocusChange),
  914. sPresContext.get(), GetBoolName(CanHandleWith(sPresContext)),
  915. sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
  916. sActiveTabParent.get()));
  917. if (aTabParent != sActiveTabParent) {
  918. MOZ_LOG(sISMLog, LogLevel::Error,
  919. (" SetInputContextForChildProcess(), FAILED, "
  920. "because non-focused tab parent tries to set input context"));
  921. return;
  922. }
  923. if (NS_WARN_IF(!CanHandleWith(sPresContext))) {
  924. MOZ_LOG(sISMLog, LogLevel::Error,
  925. (" SetInputContextForChildProcess(), FAILED, "
  926. "due to no focused presContext"));
  927. return;
  928. }
  929. if (NS_WARN_IF(!sWidget) || NS_WARN_IF(sWidget->Destroyed())) {
  930. MOZ_LOG(sISMLog, LogLevel::Error,
  931. (" SetInputContextForChildProcess(), FAILED, "
  932. "due to the widget for the nsPresContext has gone"));
  933. return;
  934. }
  935. nsCOMPtr<nsIWidget> widget(sWidget);
  936. MOZ_ASSERT(!sPresContext->GetRootWidget() ||
  937. sPresContext->GetRootWidget() == widget);
  938. MOZ_ASSERT(aInputContext.mOrigin == InputContext::ORIGIN_CONTENT);
  939. SetInputContext(widget, aInputContext, aAction);
  940. }
  941. // static
  942. void
  943. IMEStateManager::SetIMEState(const IMEState& aState,
  944. nsPresContext* aPresContext,
  945. nsIContent* aContent,
  946. nsIWidget* aWidget,
  947. InputContextAction aAction)
  948. {
  949. MOZ_LOG(sISMLog, LogLevel::Info,
  950. ("SetIMEState(aState={ mEnabled=%s, mOpen=%s }, "
  951. "aContent=0x%p (TabParent=0x%p), aWidget=0x%p, aAction={ mCause=%s, "
  952. "mFocusChange=%s })",
  953. GetIMEStateEnabledName(aState.mEnabled),
  954. GetIMEStateSetOpenName(aState.mOpen), aContent,
  955. TabParent::GetFrom(aContent), aWidget,
  956. GetActionCauseName(aAction.mCause),
  957. GetActionFocusChangeName(aAction.mFocusChange)));
  958. NS_ENSURE_TRUE_VOID(aWidget);
  959. InputContext context;
  960. context.mIMEState = aState;
  961. context.mMayBeIMEUnaware = context.mIMEState.IsEditable() &&
  962. sCheckForIMEUnawareWebApps && MayBeIMEUnawareWebApp(aContent);
  963. context.mInPrivateBrowsing =
  964. aPresContext &&
  965. nsContentUtils::IsInPrivateBrowsing(aPresContext->Document());
  966. if (aContent &&
  967. aContent->IsAnyOfHTMLElements(nsGkAtoms::input, nsGkAtoms::textarea)) {
  968. if (!aContent->IsHTMLElement(nsGkAtoms::textarea)) {
  969. // <input type=number> has an anonymous <input type=text> descendant
  970. // that gets focus whenever anyone tries to focus the number control. We
  971. // need to check if aContent is one of those anonymous text controls and,
  972. // if so, use the number control instead:
  973. nsIContent* content = aContent;
  974. HTMLInputElement* inputElement =
  975. HTMLInputElement::FromContentOrNull(aContent);
  976. if (inputElement) {
  977. HTMLInputElement* ownerNumberControl =
  978. inputElement->GetOwnerNumberControl();
  979. if (ownerNumberControl) {
  980. content = ownerNumberControl; // an <input type=number>
  981. }
  982. }
  983. content->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
  984. context.mHTMLInputType);
  985. } else {
  986. context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String());
  987. }
  988. if (Preferences::GetBool("dom.forms.inputmode", false) ||
  989. nsContentUtils::IsChromeDoc(aContent->OwnerDoc())) {
  990. aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::inputmode,
  991. context.mHTMLInputInputmode);
  992. }
  993. aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
  994. context.mActionHint);
  995. // Get the input content corresponding to the focused node,
  996. // which may be an anonymous child of the input content.
  997. nsIContent* inputContent = aContent->FindFirstNonChromeOnlyAccessContent();
  998. // If we don't have an action hint and
  999. // return won't submit the form, use "next".
  1000. if (context.mActionHint.IsEmpty() &&
  1001. inputContent->IsHTMLElement(nsGkAtoms::input)) {
  1002. bool willSubmit = false;
  1003. nsCOMPtr<nsIFormControl> control(do_QueryInterface(inputContent));
  1004. mozilla::dom::Element* formElement = nullptr;
  1005. nsCOMPtr<nsIForm> form;
  1006. if (control) {
  1007. formElement = control->GetFormElement();
  1008. // is this a form and does it have a default submit element?
  1009. if ((form = do_QueryInterface(formElement)) &&
  1010. form->GetDefaultSubmitElement()) {
  1011. willSubmit = true;
  1012. // is this an html form and does it only have a single text input element?
  1013. } else if (formElement && formElement->IsHTMLElement(nsGkAtoms::form) &&
  1014. !static_cast<dom::HTMLFormElement*>(formElement)->
  1015. ImplicitSubmissionIsDisabled()) {
  1016. willSubmit = true;
  1017. }
  1018. }
  1019. context.mActionHint.Assign(
  1020. willSubmit ? (control->GetType() == NS_FORM_INPUT_SEARCH ?
  1021. NS_LITERAL_STRING("search") : NS_LITERAL_STRING("go")) :
  1022. (formElement ?
  1023. NS_LITERAL_STRING("next") : EmptyString()));
  1024. }
  1025. }
  1026. // XXX I think that we should use nsContentUtils::IsCallerChrome() instead
  1027. // of the process type.
  1028. if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN &&
  1029. !XRE_IsContentProcess()) {
  1030. aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME;
  1031. }
  1032. SetInputContext(aWidget, context, aAction);
  1033. }
  1034. // static
  1035. void
  1036. IMEStateManager::SetInputContext(nsIWidget* aWidget,
  1037. const InputContext& aInputContext,
  1038. const InputContextAction& aAction)
  1039. {
  1040. MOZ_LOG(sISMLog, LogLevel::Info,
  1041. ("SetInputContext(aWidget=0x%p, aInputContext={ "
  1042. "mIMEState={ mEnabled=%s, mOpen=%s }, mHTMLInputType=\"%s\", "
  1043. "mHTMLInputInputmode=\"%s\", mActionHint=\"%s\", "
  1044. "mInPrivateBrowsing=%s }, "
  1045. "aAction={ mCause=%s, mAction=%s }), sActiveTabParent=0x%p",
  1046. aWidget,
  1047. GetIMEStateEnabledName(aInputContext.mIMEState.mEnabled),
  1048. GetIMEStateSetOpenName(aInputContext.mIMEState.mOpen),
  1049. NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputType).get(),
  1050. NS_ConvertUTF16toUTF8(aInputContext.mHTMLInputInputmode).get(),
  1051. NS_ConvertUTF16toUTF8(aInputContext.mActionHint).get(),
  1052. GetBoolName(aInputContext.mInPrivateBrowsing),
  1053. GetActionCauseName(aAction.mCause),
  1054. GetActionFocusChangeName(aAction.mFocusChange),
  1055. sActiveTabParent.get()));
  1056. MOZ_RELEASE_ASSERT(aWidget);
  1057. nsCOMPtr<nsIWidget> widget(aWidget);
  1058. widget->SetInputContext(aInputContext, aAction);
  1059. sActiveInputContextWidget = widget;
  1060. }
  1061. // static
  1062. void
  1063. IMEStateManager::EnsureTextCompositionArray()
  1064. {
  1065. if (sTextCompositions) {
  1066. return;
  1067. }
  1068. sTextCompositions = new TextCompositionArray();
  1069. }
  1070. // static
  1071. void
  1072. IMEStateManager::DispatchCompositionEvent(
  1073. nsINode* aEventTargetNode,
  1074. nsPresContext* aPresContext,
  1075. WidgetCompositionEvent* aCompositionEvent,
  1076. nsEventStatus* aStatus,
  1077. EventDispatchingCallback* aCallBack,
  1078. bool aIsSynthesized)
  1079. {
  1080. RefPtr<TabParent> tabParent =
  1081. aEventTargetNode->IsContent() ?
  1082. TabParent::GetFrom(aEventTargetNode->AsContent()) : nullptr;
  1083. MOZ_LOG(sISMLog, LogLevel::Info,
  1084. ("DispatchCompositionEvent(aNode=0x%p, "
  1085. "aPresContext=0x%p, aCompositionEvent={ mMessage=%s, "
  1086. "mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
  1087. "mOriginProcessID=0x%X }, mWidget(0x%p)={ "
  1088. "GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
  1089. "mOriginProcessID=0x%X }, Destroyed()=%s }, "
  1090. "mFlags={ mIsTrusted=%s, mPropagationStopped=%s } }, "
  1091. "aIsSynthesized=%s), tabParent=%p",
  1092. aEventTargetNode, aPresContext,
  1093. ToChar(aCompositionEvent->mMessage),
  1094. aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
  1095. aCompositionEvent->mNativeIMEContext.mOriginProcessID,
  1096. aCompositionEvent->mWidget.get(),
  1097. aCompositionEvent->mWidget->GetNativeIMEContext().mRawNativeIMEContext,
  1098. aCompositionEvent->mWidget->GetNativeIMEContext().mOriginProcessID,
  1099. GetBoolName(aCompositionEvent->mWidget->Destroyed()),
  1100. GetBoolName(aCompositionEvent->mFlags.mIsTrusted),
  1101. GetBoolName(aCompositionEvent->mFlags.mPropagationStopped),
  1102. GetBoolName(aIsSynthesized), tabParent.get()));
  1103. if (!aCompositionEvent->IsTrusted() ||
  1104. aCompositionEvent->PropagationStopped()) {
  1105. return;
  1106. }
  1107. MOZ_ASSERT(aCompositionEvent->mMessage != eCompositionUpdate,
  1108. "compositionupdate event shouldn't be dispatched manually");
  1109. EnsureTextCompositionArray();
  1110. RefPtr<TextComposition> composition =
  1111. sTextCompositions->GetCompositionFor(aCompositionEvent);
  1112. if (!composition) {
  1113. // If synthesized event comes after delayed native composition events
  1114. // for request of commit or cancel, we should ignore it.
  1115. if (NS_WARN_IF(aIsSynthesized)) {
  1116. return;
  1117. }
  1118. MOZ_LOG(sISMLog, LogLevel::Debug,
  1119. (" DispatchCompositionEvent(), "
  1120. "adding new TextComposition to the array"));
  1121. MOZ_ASSERT(aCompositionEvent->mMessage == eCompositionStart);
  1122. composition =
  1123. new TextComposition(aPresContext, aEventTargetNode, tabParent,
  1124. aCompositionEvent);
  1125. sTextCompositions->AppendElement(composition);
  1126. }
  1127. #ifdef DEBUG
  1128. else {
  1129. MOZ_ASSERT(aCompositionEvent->mMessage != eCompositionStart);
  1130. }
  1131. #endif // #ifdef DEBUG
  1132. // Dispatch the event on composing target.
  1133. composition->DispatchCompositionEvent(aCompositionEvent, aStatus, aCallBack,
  1134. aIsSynthesized);
  1135. // WARNING: the |composition| might have been destroyed already.
  1136. // Remove the ended composition from the array.
  1137. // NOTE: When TextComposition is synthesizing compositionend event for
  1138. // emulating a commit, the instance shouldn't be removed from the array
  1139. // because IME may perform it later. Then, we need to ignore the
  1140. // following commit events in TextComposition::DispatchEvent().
  1141. // However, if commit or cancel for a request is performed synchronously
  1142. // during not safe to dispatch events, PresShell must have discarded
  1143. // compositionend event. Then, the synthesized compositionend event is
  1144. // the last event for the composition. In this case, we need to
  1145. // destroy the TextComposition with synthesized compositionend event.
  1146. if ((!aIsSynthesized ||
  1147. composition->WasNativeCompositionEndEventDiscarded()) &&
  1148. aCompositionEvent->CausesDOMCompositionEndEvent()) {
  1149. TextCompositionArray::index_type i =
  1150. sTextCompositions->IndexOf(aCompositionEvent->mWidget);
  1151. if (i != TextCompositionArray::NoIndex) {
  1152. MOZ_LOG(sISMLog, LogLevel::Debug,
  1153. (" DispatchCompositionEvent(), "
  1154. "removing TextComposition from the array since NS_COMPOSTION_END "
  1155. "was dispatched"));
  1156. sTextCompositions->ElementAt(i)->Destroy();
  1157. sTextCompositions->RemoveElementAt(i);
  1158. }
  1159. }
  1160. }
  1161. // static
  1162. IMEContentObserver*
  1163. IMEStateManager::GetActiveContentObserver()
  1164. {
  1165. return sActiveIMEContentObserver;
  1166. }
  1167. // static
  1168. nsIContent*
  1169. IMEStateManager::GetRootContent(nsPresContext* aPresContext)
  1170. {
  1171. nsIDocument* doc = aPresContext->Document();
  1172. if (NS_WARN_IF(!doc)) {
  1173. return nullptr;
  1174. }
  1175. return doc->GetRootElement();
  1176. }
  1177. // static
  1178. void
  1179. IMEStateManager::HandleSelectionEvent(nsPresContext* aPresContext,
  1180. nsIContent* aEventTargetContent,
  1181. WidgetSelectionEvent* aSelectionEvent)
  1182. {
  1183. nsIContent* eventTargetContent =
  1184. aEventTargetContent ? aEventTargetContent :
  1185. GetRootContent(aPresContext);
  1186. RefPtr<TabParent> tabParent =
  1187. eventTargetContent ? TabParent::GetFrom(eventTargetContent) : nullptr;
  1188. MOZ_LOG(sISMLog, LogLevel::Info,
  1189. ("HandleSelectionEvent(aPresContext=0x%p, "
  1190. "aEventTargetContent=0x%p, aSelectionEvent={ mMessage=%s, "
  1191. "mFlags={ mIsTrusted=%s } }), tabParent=%p",
  1192. aPresContext, aEventTargetContent,
  1193. ToChar(aSelectionEvent->mMessage),
  1194. GetBoolName(aSelectionEvent->mFlags.mIsTrusted),
  1195. tabParent.get()));
  1196. if (!aSelectionEvent->IsTrusted()) {
  1197. return;
  1198. }
  1199. RefPtr<TextComposition> composition = sTextCompositions ?
  1200. sTextCompositions->GetCompositionFor(aSelectionEvent->mWidget) : nullptr;
  1201. if (composition) {
  1202. // When there is a composition, TextComposition should guarantee that the
  1203. // selection event will be handled in same target as composition events.
  1204. composition->HandleSelectionEvent(aSelectionEvent);
  1205. } else {
  1206. // When there is no composition, the selection event should be handled
  1207. // in the aPresContext or tabParent.
  1208. TextComposition::HandleSelectionEvent(aPresContext, tabParent,
  1209. aSelectionEvent);
  1210. }
  1211. }
  1212. // static
  1213. void
  1214. IMEStateManager::OnCompositionEventDiscarded(
  1215. WidgetCompositionEvent* aCompositionEvent)
  1216. {
  1217. // Note that this method is never called for synthesized events for emulating
  1218. // commit or cancel composition.
  1219. MOZ_LOG(sISMLog, LogLevel::Info,
  1220. ("OnCompositionEventDiscarded(aCompositionEvent={ "
  1221. "mMessage=%s, mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
  1222. "mOriginProcessID=0x%X }, mWidget(0x%p)={ "
  1223. "GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
  1224. "mOriginProcessID=0x%X }, Destroyed()=%s }, "
  1225. "mFlags={ mIsTrusted=%s } })",
  1226. ToChar(aCompositionEvent->mMessage),
  1227. aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
  1228. aCompositionEvent->mNativeIMEContext.mOriginProcessID,
  1229. aCompositionEvent->mWidget.get(),
  1230. aCompositionEvent->mWidget->GetNativeIMEContext().mRawNativeIMEContext,
  1231. aCompositionEvent->mWidget->GetNativeIMEContext().mOriginProcessID,
  1232. GetBoolName(aCompositionEvent->mWidget->Destroyed()),
  1233. GetBoolName(aCompositionEvent->mFlags.mIsTrusted)));
  1234. if (!aCompositionEvent->IsTrusted()) {
  1235. return;
  1236. }
  1237. // Ignore compositionstart for now because sTextCompositions may not have
  1238. // been created yet.
  1239. if (aCompositionEvent->mMessage == eCompositionStart) {
  1240. return;
  1241. }
  1242. RefPtr<TextComposition> composition =
  1243. sTextCompositions->GetCompositionFor(aCompositionEvent->mWidget);
  1244. if (!composition) {
  1245. // If the PresShell has been being destroyed during composition,
  1246. // a TextComposition instance for the composition was already removed from
  1247. // the array and destroyed in OnDestroyPresContext(). Therefore, we may
  1248. // fail to retrieve a TextComposition instance here.
  1249. MOZ_LOG(sISMLog, LogLevel::Info,
  1250. (" OnCompositionEventDiscarded(), "
  1251. "TextComposition instance for the widget has already gone"));
  1252. return;
  1253. }
  1254. composition->OnCompositionEventDiscarded(aCompositionEvent);
  1255. }
  1256. // static
  1257. nsresult
  1258. IMEStateManager::NotifyIME(IMEMessage aMessage,
  1259. nsIWidget* aWidget,
  1260. bool aOriginIsRemote)
  1261. {
  1262. return IMEStateManager::NotifyIME(IMENotification(aMessage), aWidget,
  1263. aOriginIsRemote);
  1264. }
  1265. // static
  1266. nsresult
  1267. IMEStateManager::NotifyIME(const IMENotification& aNotification,
  1268. nsIWidget* aWidget,
  1269. bool aOriginIsRemote)
  1270. {
  1271. MOZ_LOG(sISMLog, LogLevel::Info,
  1272. ("NotifyIME(aNotification={ mMessage=%s }, "
  1273. "aWidget=0x%p, aOriginIsRemote=%s), sFocusedIMEWidget=0x%p, "
  1274. "sRemoteHasFocus=%s",
  1275. ToChar(aNotification.mMessage), aWidget,
  1276. GetBoolName(aOriginIsRemote), sFocusedIMEWidget,
  1277. GetBoolName(sRemoteHasFocus)));
  1278. if (NS_WARN_IF(!aWidget)) {
  1279. MOZ_LOG(sISMLog, LogLevel::Error,
  1280. (" NotifyIME(), FAILED due to no widget"));
  1281. return NS_ERROR_INVALID_ARG;
  1282. }
  1283. switch (aNotification.mMessage) {
  1284. case NOTIFY_IME_OF_FOCUS: {
  1285. if (sFocusedIMEWidget) {
  1286. if (NS_WARN_IF(!sRemoteHasFocus && !aOriginIsRemote)) {
  1287. MOZ_LOG(sISMLog, LogLevel::Error,
  1288. (" NotifyIME(), although, this process is "
  1289. "getting IME focus but there was focused IME widget"));
  1290. } else {
  1291. MOZ_LOG(sISMLog, LogLevel::Info,
  1292. (" NotifyIME(), tries to notify IME of "
  1293. "blur first because remote process's blur notification hasn't "
  1294. "been received yet..."));
  1295. }
  1296. nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
  1297. sFocusedIMEWidget = nullptr;
  1298. sRemoteHasFocus = false;
  1299. focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
  1300. }
  1301. sRemoteHasFocus = aOriginIsRemote;
  1302. sFocusedIMEWidget = aWidget;
  1303. nsCOMPtr<nsIWidget> widget(aWidget);
  1304. return widget->NotifyIME(aNotification);
  1305. }
  1306. case NOTIFY_IME_OF_BLUR: {
  1307. if (!sRemoteHasFocus && aOriginIsRemote) {
  1308. MOZ_LOG(sISMLog, LogLevel::Info,
  1309. (" NotifyIME(), received blur notification "
  1310. "after another one has focus, nothing to do..."));
  1311. return NS_OK;
  1312. }
  1313. if (NS_WARN_IF(sRemoteHasFocus && !aOriginIsRemote)) {
  1314. MOZ_LOG(sISMLog, LogLevel::Error,
  1315. (" NotifyIME(), FAILED, received blur "
  1316. "notification from this process but the remote has focus"));
  1317. return NS_OK;
  1318. }
  1319. if (!sFocusedIMEWidget && aOriginIsRemote) {
  1320. MOZ_LOG(sISMLog, LogLevel::Info,
  1321. (" NotifyIME(), received blur notification "
  1322. "but the remote has already lost focus"));
  1323. return NS_OK;
  1324. }
  1325. if (NS_WARN_IF(!sFocusedIMEWidget)) {
  1326. MOZ_LOG(sISMLog, LogLevel::Error,
  1327. (" NotifyIME(), FAILED, received blur "
  1328. "notification but there is no focused IME widget"));
  1329. return NS_OK;
  1330. }
  1331. if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
  1332. MOZ_LOG(sISMLog, LogLevel::Error,
  1333. (" NotifyIME(), FAILED, received blur "
  1334. "notification but there is no focused IME widget"));
  1335. return NS_OK;
  1336. }
  1337. nsCOMPtr<nsIWidget> focusedIMEWidget(sFocusedIMEWidget);
  1338. sFocusedIMEWidget = nullptr;
  1339. sRemoteHasFocus = false;
  1340. return focusedIMEWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
  1341. }
  1342. case NOTIFY_IME_OF_SELECTION_CHANGE:
  1343. case NOTIFY_IME_OF_TEXT_CHANGE:
  1344. case NOTIFY_IME_OF_POSITION_CHANGE:
  1345. case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
  1346. case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED: {
  1347. if (!sRemoteHasFocus && aOriginIsRemote) {
  1348. MOZ_LOG(sISMLog, LogLevel::Info,
  1349. (" NotifyIME(), received content change "
  1350. "notification from the remote but it's already lost focus"));
  1351. return NS_OK;
  1352. }
  1353. if (NS_WARN_IF(sRemoteHasFocus && !aOriginIsRemote)) {
  1354. MOZ_LOG(sISMLog, LogLevel::Error,
  1355. (" NotifyIME(), FAILED, received content "
  1356. "change notification from this process but the remote has already "
  1357. "gotten focus"));
  1358. return NS_OK;
  1359. }
  1360. if (!sFocusedIMEWidget) {
  1361. MOZ_LOG(sISMLog, LogLevel::Info,
  1362. (" NotifyIME(), received content change "
  1363. "notification but there is no focused IME widget"));
  1364. return NS_OK;
  1365. }
  1366. if (NS_WARN_IF(sFocusedIMEWidget != aWidget)) {
  1367. MOZ_LOG(sISMLog, LogLevel::Error,
  1368. (" NotifyIME(), FAILED, received content "
  1369. "change notification for IME which has already lost focus, so, "
  1370. "nothing to do..."));
  1371. return NS_OK;
  1372. }
  1373. nsCOMPtr<nsIWidget> widget(aWidget);
  1374. return widget->NotifyIME(aNotification);
  1375. }
  1376. default:
  1377. // Other notifications should be sent only when there is composition.
  1378. // So, we need to handle the others below.
  1379. break;
  1380. }
  1381. RefPtr<TextComposition> composition;
  1382. if (sTextCompositions) {
  1383. composition = sTextCompositions->GetCompositionFor(aWidget);
  1384. }
  1385. bool isSynthesizedForTests =
  1386. composition && composition->IsSynthesizedForTests();
  1387. MOZ_LOG(sISMLog, LogLevel::Info,
  1388. (" NotifyIME(), composition=0x%p, "
  1389. "composition->IsSynthesizedForTests()=%s",
  1390. composition.get(), GetBoolName(isSynthesizedForTests)));
  1391. switch (aNotification.mMessage) {
  1392. case REQUEST_TO_COMMIT_COMPOSITION:
  1393. return composition ?
  1394. composition->RequestToCommit(aWidget, false) : NS_OK;
  1395. case REQUEST_TO_CANCEL_COMPOSITION:
  1396. return composition ?
  1397. composition->RequestToCommit(aWidget, true) : NS_OK;
  1398. default:
  1399. MOZ_CRASH("Unsupported notification");
  1400. }
  1401. MOZ_CRASH(
  1402. "Failed to handle the notification for non-synthesized composition");
  1403. return NS_ERROR_FAILURE;
  1404. }
  1405. // static
  1406. nsresult
  1407. IMEStateManager::NotifyIME(IMEMessage aMessage,
  1408. nsPresContext* aPresContext,
  1409. bool aOriginIsRemote)
  1410. {
  1411. MOZ_LOG(sISMLog, LogLevel::Info,
  1412. ("NotifyIME(aMessage=%s, aPresContext=0x%p, aOriginIsRemote=%s)",
  1413. ToChar(aMessage), aPresContext, GetBoolName(aOriginIsRemote)));
  1414. if (NS_WARN_IF(!CanHandleWith(aPresContext))) {
  1415. return NS_ERROR_INVALID_ARG;
  1416. }
  1417. nsIWidget* widget = aPresContext->GetRootWidget();
  1418. if (NS_WARN_IF(!widget)) {
  1419. MOZ_LOG(sISMLog, LogLevel::Error,
  1420. (" NotifyIME(), FAILED due to no widget for the "
  1421. "nsPresContext"));
  1422. return NS_ERROR_NOT_AVAILABLE;
  1423. }
  1424. return NotifyIME(aMessage, widget, aOriginIsRemote);
  1425. }
  1426. // static
  1427. bool
  1428. IMEStateManager::IsEditable(nsINode* node)
  1429. {
  1430. if (node->IsEditable()) {
  1431. return true;
  1432. }
  1433. // |node| might be readwrite (for example, a text control)
  1434. if (node->IsElement() &&
  1435. node->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
  1436. return true;
  1437. }
  1438. return false;
  1439. }
  1440. // static
  1441. nsINode*
  1442. IMEStateManager::GetRootEditableNode(nsPresContext* aPresContext,
  1443. nsIContent* aContent)
  1444. {
  1445. if (aContent) {
  1446. nsINode* root = nullptr;
  1447. nsINode* node = aContent;
  1448. while (node && IsEditable(node)) {
  1449. // If the node has independent selection like <input type="text"> or
  1450. // <textarea>, the node should be the root editable node for aContent.
  1451. // FYI: <select> element also has independent selection but IsEditable()
  1452. // returns false.
  1453. // XXX: If somebody adds new editable element which has independent
  1454. // selection but doesn't own editor, we'll need more checks here.
  1455. if (node->IsContent() &&
  1456. node->AsContent()->HasIndependentSelection()) {
  1457. return node;
  1458. }
  1459. root = node;
  1460. node = node->GetParentNode();
  1461. }
  1462. return root;
  1463. }
  1464. if (aPresContext) {
  1465. nsIDocument* document = aPresContext->Document();
  1466. if (document && document->IsEditable()) {
  1467. return document;
  1468. }
  1469. }
  1470. return nullptr;
  1471. }
  1472. // static
  1473. bool
  1474. IMEStateManager::IsIMEObserverNeeded(const IMEState& aState)
  1475. {
  1476. return aState.MaybeEditable();
  1477. }
  1478. // static
  1479. void
  1480. IMEStateManager::DestroyIMEContentObserver()
  1481. {
  1482. MOZ_LOG(sISMLog, LogLevel::Info,
  1483. ("DestroyIMEContentObserver(), sActiveIMEContentObserver=0x%p",
  1484. sActiveIMEContentObserver.get()));
  1485. if (!sActiveIMEContentObserver) {
  1486. MOZ_LOG(sISMLog, LogLevel::Debug,
  1487. (" DestroyIMEContentObserver() does nothing"));
  1488. return;
  1489. }
  1490. MOZ_LOG(sISMLog, LogLevel::Debug,
  1491. (" DestroyIMEContentObserver(), destroying "
  1492. "the active IMEContentObserver..."));
  1493. RefPtr<IMEContentObserver> tsm = sActiveIMEContentObserver.get();
  1494. sActiveIMEContentObserver = nullptr;
  1495. tsm->Destroy();
  1496. }
  1497. // static
  1498. void
  1499. IMEStateManager::CreateIMEContentObserver(nsIEditor* aEditor)
  1500. {
  1501. MOZ_LOG(sISMLog, LogLevel::Info,
  1502. ("CreateIMEContentObserver(aEditor=0x%p), "
  1503. "sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s), "
  1504. "sActiveIMEContentObserver=0x%p, "
  1505. "sActiveIMEContentObserver->IsManaging(sPresContext, sContent)=%s",
  1506. aEditor, sPresContext.get(), sContent.get(),
  1507. sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
  1508. sActiveIMEContentObserver.get(),
  1509. GetBoolName(sActiveIMEContentObserver ?
  1510. sActiveIMEContentObserver->IsManaging(sPresContext, sContent) : false)));
  1511. if (NS_WARN_IF(sActiveIMEContentObserver)) {
  1512. MOZ_LOG(sISMLog, LogLevel::Error,
  1513. (" CreateIMEContentObserver(), FAILED due to "
  1514. "there is already an active IMEContentObserver"));
  1515. MOZ_ASSERT(sActiveIMEContentObserver->IsManaging(sPresContext, sContent));
  1516. return;
  1517. }
  1518. if (!sWidget || NS_WARN_IF(sWidget->Destroyed())) {
  1519. MOZ_LOG(sISMLog, LogLevel::Error,
  1520. (" CreateIMEContentObserver(), FAILED due to "
  1521. "the widget for the nsPresContext has gone"));
  1522. return; // Sometimes, there are no widgets.
  1523. }
  1524. nsCOMPtr<nsIWidget> widget(sWidget);
  1525. // If it's not text editable, we don't need to create IMEContentObserver.
  1526. if (!IsIMEObserverNeeded(widget->GetInputContext().mIMEState)) {
  1527. MOZ_LOG(sISMLog, LogLevel::Debug,
  1528. (" CreateIMEContentObserver() doesn't create "
  1529. "IMEContentObserver because of non-editable IME state"));
  1530. return;
  1531. }
  1532. if (NS_WARN_IF(widget->Destroyed())) {
  1533. MOZ_LOG(sISMLog, LogLevel::Error,
  1534. (" CreateIMEContentObserver(), FAILED due to "
  1535. "the widget for the nsPresContext has gone"));
  1536. return;
  1537. }
  1538. MOZ_ASSERT(sPresContext->GetRootWidget() == widget);
  1539. MOZ_LOG(sISMLog, LogLevel::Debug,
  1540. (" CreateIMEContentObserver() is creating an "
  1541. "IMEContentObserver instance..."));
  1542. sActiveIMEContentObserver = new IMEContentObserver();
  1543. // IMEContentObserver::Init() might create another IMEContentObserver
  1544. // instance. So, sActiveIMEContentObserver would be replaced with new one.
  1545. // We should hold the current instance here.
  1546. RefPtr<IMEContentObserver> activeIMEContentObserver(sActiveIMEContentObserver);
  1547. activeIMEContentObserver->Init(widget, sPresContext, sContent, aEditor);
  1548. }
  1549. // static
  1550. nsresult
  1551. IMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSelection,
  1552. nsIContent** aRootContent)
  1553. {
  1554. if (!sActiveIMEContentObserver) {
  1555. return NS_ERROR_NOT_AVAILABLE;
  1556. }
  1557. return sActiveIMEContentObserver->GetSelectionAndRoot(aSelection,
  1558. aRootContent);
  1559. }
  1560. // static
  1561. already_AddRefed<TextComposition>
  1562. IMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
  1563. {
  1564. if (!sTextCompositions) {
  1565. return nullptr;
  1566. }
  1567. RefPtr<TextComposition> textComposition =
  1568. sTextCompositions->GetCompositionFor(aWidget);
  1569. return textComposition.forget();
  1570. }
  1571. // static
  1572. already_AddRefed<TextComposition>
  1573. IMEStateManager::GetTextCompositionFor(
  1574. const WidgetCompositionEvent* aCompositionEvent)
  1575. {
  1576. if (!sTextCompositions) {
  1577. return nullptr;
  1578. }
  1579. RefPtr<TextComposition> textComposition =
  1580. sTextCompositions->GetCompositionFor(aCompositionEvent);
  1581. return textComposition.forget();
  1582. }
  1583. // static
  1584. already_AddRefed<TextComposition>
  1585. IMEStateManager::GetTextCompositionFor(nsPresContext* aPresContext)
  1586. {
  1587. if (!sTextCompositions) {
  1588. return nullptr;
  1589. }
  1590. RefPtr<TextComposition> textComposition =
  1591. sTextCompositions->GetCompositionFor(aPresContext);
  1592. return textComposition.forget();
  1593. }
  1594. } // namespace mozilla