nsBaseWidget.cpp 109 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309
  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/ArrayUtils.h"
  6. #include "mozilla/UniquePtr.h"
  7. #include "mozilla/TextEventDispatcher.h"
  8. #include "mozilla/TextEventDispatcherListener.h"
  9. #include "mozilla/layers/CompositorBridgeChild.h"
  10. #include "mozilla/layers/CompositorBridgeParent.h"
  11. #include "mozilla/layers/ImageBridgeChild.h"
  12. #include "nsBaseWidget.h"
  13. #include "nsDeviceContext.h"
  14. #include "nsCOMPtr.h"
  15. #include "nsGfxCIID.h"
  16. #include "nsWidgetsCID.h"
  17. #include "nsServiceManagerUtils.h"
  18. #include "nsIKeyEventInPluginCallback.h"
  19. #include "nsIScreenManager.h"
  20. #include "nsAppDirectoryServiceDefs.h"
  21. #include "nsISimpleEnumerator.h"
  22. #include "nsIContent.h"
  23. #include "nsIDocument.h"
  24. #include "nsIPresShell.h"
  25. #include "nsIServiceManager.h"
  26. #include "mozilla/Preferences.h"
  27. #include "BasicLayers.h"
  28. #include "ClientLayerManager.h"
  29. #include "mozilla/layers/Compositor.h"
  30. #include "nsIXULRuntime.h"
  31. #include "nsIXULWindow.h"
  32. #include "nsIBaseWindow.h"
  33. #include "nsXULPopupManager.h"
  34. #include "nsIWidgetListener.h"
  35. #include "nsIGfxInfo.h"
  36. #include "npapi.h"
  37. #include "X11UndefineNone.h"
  38. #include "base/thread.h"
  39. #include "prdtoa.h"
  40. #include "prenv.h"
  41. #include "mozilla/Attributes.h"
  42. #include "mozilla/Unused.h"
  43. #include "nsContentUtils.h"
  44. #include "gfxPrefs.h"
  45. #include "mozilla/gfx/2D.h"
  46. #include "mozilla/MouseEvents.h"
  47. #include "GLConsts.h"
  48. #include "mozilla/Unused.h"
  49. #include "mozilla/IMEStateManager.h"
  50. #include "mozilla/VsyncDispatcher.h"
  51. #include "mozilla/layers/IAPZCTreeManager.h"
  52. #include "mozilla/layers/APZEventState.h"
  53. #include "mozilla/layers/APZThreadUtils.h"
  54. #include "mozilla/layers/ChromeProcessController.h"
  55. #include "mozilla/layers/InputAPZContext.h"
  56. #include "mozilla/layers/APZCCallbackHelper.h"
  57. #include "mozilla/dom/ContentChild.h"
  58. #include "mozilla/dom/TabParent.h"
  59. #include "mozilla/gfx/GPUProcessManager.h"
  60. #include "mozilla/Move.h"
  61. #include "mozilla/Services.h"
  62. #include "mozilla/Sprintf.h"
  63. #include "nsRefPtrHashtable.h"
  64. #include "TouchEvents.h"
  65. #include "WritingModes.h"
  66. #include "InputData.h"
  67. #include "FrameLayerBuilder.h"
  68. #ifdef ACCESSIBILITY
  69. #include "nsAccessibilityService.h"
  70. #endif
  71. #include "gfxConfig.h"
  72. #include "mozilla/layers/CompositorSession.h"
  73. #ifdef DEBUG
  74. #include "nsIObserver.h"
  75. static void debug_RegisterPrefCallbacks();
  76. #endif
  77. #ifdef NOISY_WIDGET_LEAKS
  78. static int32_t gNumWidgets;
  79. #endif
  80. #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
  81. static nsRefPtrHashtable<nsVoidPtrHashKey, nsIWidget>* sPluginWidgetList;
  82. #endif
  83. nsIRollupListener* nsBaseWidget::gRollupListener = nullptr;
  84. using namespace mozilla::dom;
  85. using namespace mozilla::layers;
  86. using namespace mozilla::ipc;
  87. using namespace mozilla::widget;
  88. using namespace mozilla;
  89. using base::Thread;
  90. nsIContent* nsBaseWidget::mLastRollup = nullptr;
  91. // Global user preference for disabling native theme. Used
  92. // in NativeWindowTheme.
  93. bool gDisableNativeTheme = false;
  94. // Async pump timer during injected long touch taps
  95. #define TOUCH_INJECT_PUMP_TIMER_MSEC 50
  96. #define TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC 1500
  97. int32_t nsIWidget::sPointerIdCounter = 0;
  98. // Some statics from nsIWidget.h
  99. /*static*/ uint64_t AutoObserverNotifier::sObserverId = 0;
  100. /*static*/ nsDataHashtable<nsUint64HashKey, nsCOMPtr<nsIObserver>> AutoObserverNotifier::sSavedObservers;
  101. namespace mozilla {
  102. namespace widget {
  103. void
  104. IMENotification::SelectionChangeDataBase::SetWritingMode(
  105. const WritingMode& aWritingMode)
  106. {
  107. mWritingMode = aWritingMode.mWritingMode;
  108. }
  109. WritingMode
  110. IMENotification::SelectionChangeDataBase::GetWritingMode() const
  111. {
  112. return WritingMode(mWritingMode);
  113. }
  114. } // namespace widget
  115. } // namespace mozilla
  116. nsAutoRollup::nsAutoRollup()
  117. {
  118. // remember if mLastRollup was null, and only clear it upon destruction
  119. // if so. This prevents recursive usage of nsAutoRollup from clearing
  120. // mLastRollup when it shouldn't.
  121. wasClear = !nsBaseWidget::mLastRollup;
  122. }
  123. nsAutoRollup::~nsAutoRollup()
  124. {
  125. if (nsBaseWidget::mLastRollup && wasClear) {
  126. NS_RELEASE(nsBaseWidget::mLastRollup);
  127. }
  128. }
  129. NS_IMPL_ISUPPORTS(nsBaseWidget, nsIWidget, nsISupportsWeakReference)
  130. //-------------------------------------------------------------------------
  131. //
  132. // nsBaseWidget constructor
  133. //
  134. //-------------------------------------------------------------------------
  135. nsBaseWidget::nsBaseWidget()
  136. : mWidgetListener(nullptr)
  137. , mAttachedWidgetListener(nullptr)
  138. , mPreviouslyAttachedWidgetListener(nullptr)
  139. , mLayerManager(nullptr)
  140. , mCompositorVsyncDispatcher(nullptr)
  141. , mCursor(eCursor_standard)
  142. , mBorderStyle(eBorderStyle_none)
  143. , mBounds(0,0,0,0)
  144. , mOriginalBounds(nullptr)
  145. , mClipRectCount(0)
  146. , mSizeMode(nsSizeMode_Normal)
  147. , mPopupLevel(ePopupLevelTop)
  148. , mPopupType(ePopupTypeAny)
  149. , mCompositorWidgetDelegate(nullptr)
  150. , mUpdateCursor(true)
  151. , mUseAttachedEvents(false)
  152. , mIMEHasFocus(false)
  153. #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
  154. , mAccessibilityInUseFlag(false)
  155. #endif
  156. {
  157. #ifdef NOISY_WIDGET_LEAKS
  158. gNumWidgets++;
  159. printf("WIDGETS+ = %d\n", gNumWidgets);
  160. #endif
  161. #ifdef DEBUG
  162. debug_RegisterPrefCallbacks();
  163. #endif
  164. #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
  165. if (!sPluginWidgetList) {
  166. sPluginWidgetList = new nsRefPtrHashtable<nsVoidPtrHashKey, nsIWidget>();
  167. }
  168. #endif
  169. mShutdownObserver = new WidgetShutdownObserver(this);
  170. }
  171. NS_IMPL_ISUPPORTS(WidgetShutdownObserver, nsIObserver)
  172. WidgetShutdownObserver::WidgetShutdownObserver(nsBaseWidget* aWidget) :
  173. mWidget(aWidget),
  174. mRegistered(false)
  175. {
  176. Register();
  177. }
  178. WidgetShutdownObserver::~WidgetShutdownObserver()
  179. {
  180. // No need to call Unregister(), we can't be destroyed until nsBaseWidget
  181. // gets torn down. The observer service and nsBaseWidget have a ref on us
  182. // so nsBaseWidget has to call Unregister and then clear its ref.
  183. }
  184. NS_IMETHODIMP
  185. WidgetShutdownObserver::Observe(nsISupports *aSubject,
  186. const char *aTopic,
  187. const char16_t *aData)
  188. {
  189. if (mWidget && !strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
  190. RefPtr<nsBaseWidget> widget(mWidget);
  191. widget->Shutdown();
  192. }
  193. return NS_OK;
  194. }
  195. void
  196. WidgetShutdownObserver::Register()
  197. {
  198. if (!mRegistered) {
  199. mRegistered = true;
  200. nsContentUtils::RegisterShutdownObserver(this);
  201. }
  202. }
  203. void
  204. WidgetShutdownObserver::Unregister()
  205. {
  206. if (mRegistered) {
  207. mWidget = nullptr;
  208. nsContentUtils::UnregisterShutdownObserver(this);
  209. mRegistered = false;
  210. }
  211. }
  212. void
  213. nsBaseWidget::Shutdown()
  214. {
  215. RevokeTransactionIdAllocator();
  216. DestroyCompositor();
  217. FreeShutdownObserver();
  218. #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
  219. if (sPluginWidgetList) {
  220. delete sPluginWidgetList;
  221. sPluginWidgetList = nullptr;
  222. }
  223. #endif
  224. }
  225. void nsBaseWidget::DestroyCompositor()
  226. {
  227. // We release this before releasing the compositor, since it may hold the
  228. // last reference to our ClientLayerManager. ClientLayerManager's dtor can
  229. // trigger a paint, creating a new compositor, and we don't want to re-use
  230. // the old vsync dispatcher.
  231. if (mCompositorVsyncDispatcher) {
  232. mCompositorVsyncDispatcher->Shutdown();
  233. mCompositorVsyncDispatcher = nullptr;
  234. }
  235. // The compositor shutdown sequence looks like this:
  236. // 1. CompositorSession calls CompositorBridgeChild::Destroy.
  237. // 2. CompositorBridgeChild synchronously sends WillClose.
  238. // 3. CompositorBridgeParent releases some resources (such as the layer
  239. // manager, compositor, and widget).
  240. // 4. CompositorBridgeChild::Destroy returns.
  241. // 5. Asynchronously, CompositorBridgeParent::ActorDestroy will fire on the
  242. // compositor thread when the I/O thread closes the IPC channel.
  243. // 6. Step 5 will schedule DeferredDestroy on the compositor thread, which
  244. // releases the reference CompositorBridgeParent holds to itself.
  245. //
  246. // When CompositorSession::Shutdown returns, we assume the compositor is gone
  247. // or will be gone very soon.
  248. if (mCompositorSession) {
  249. ReleaseContentController();
  250. mAPZC = nullptr;
  251. mCompositorWidgetDelegate = nullptr;
  252. mCompositorBridgeChild = nullptr;
  253. // XXX CompositorBridgeChild and CompositorBridgeParent might be re-created in
  254. // ClientLayerManager destructor. See bug 1133426.
  255. RefPtr<CompositorSession> session = mCompositorSession.forget();
  256. session->Shutdown();
  257. }
  258. }
  259. // This prevents the layer manager from starting a new transaction during
  260. // shutdown.
  261. void
  262. nsBaseWidget::RevokeTransactionIdAllocator()
  263. {
  264. if (!mLayerManager) {
  265. return;
  266. }
  267. ClientLayerManager* clm = mLayerManager->AsClientLayerManager();
  268. if (!clm) {
  269. return;
  270. }
  271. clm->SetTransactionIdAllocator(nullptr);
  272. }
  273. void nsBaseWidget::ReleaseContentController()
  274. {
  275. if (mRootContentController) {
  276. mRootContentController->Destroy();
  277. mRootContentController = nullptr;
  278. }
  279. }
  280. void nsBaseWidget::DestroyLayerManager()
  281. {
  282. if (mLayerManager) {
  283. mLayerManager->Destroy();
  284. mLayerManager = nullptr;
  285. }
  286. DestroyCompositor();
  287. }
  288. void
  289. nsBaseWidget::OnRenderingDeviceReset()
  290. {
  291. if (!mLayerManager || !mCompositorSession) {
  292. return;
  293. }
  294. nsTArray<LayersBackend> backendHints;
  295. gfxPlatform::GetPlatform()->GetCompositorBackends(ComputeShouldAccelerate(), backendHints);
  296. // If the existing compositor does not use acceleration, and this widget
  297. // should not be accelerated, then there's no point in resetting.
  298. //
  299. // Note that if this widget should be accelerated, but instead has a basic
  300. // compositor, we still reset just in case we're now in the position to get
  301. // accelerated layers again.
  302. RefPtr<ClientLayerManager> clm = mLayerManager->AsClientLayerManager();
  303. if (!ComputeShouldAccelerate() &&
  304. clm->GetTextureFactoryIdentifier().mParentBackend != LayersBackend::LAYERS_BASIC)
  305. {
  306. return;
  307. }
  308. // Recreate the compositor.
  309. TextureFactoryIdentifier identifier;
  310. if (!mCompositorSession->Reset(backendHints, &identifier)) {
  311. // No action was taken, so we don't have to do anything.
  312. return;
  313. }
  314. // Invalidate all layers.
  315. FrameLayerBuilder::InvalidateAllLayers(mLayerManager);
  316. // Update the texture factory identifier.
  317. clm->UpdateTextureFactoryIdentifier(identifier);
  318. ImageBridgeChild::IdentifyCompositorTextureHost(identifier);
  319. }
  320. void
  321. nsBaseWidget::FreeShutdownObserver()
  322. {
  323. if (mShutdownObserver) {
  324. mShutdownObserver->Unregister();
  325. }
  326. mShutdownObserver = nullptr;
  327. }
  328. //-------------------------------------------------------------------------
  329. //
  330. // nsBaseWidget destructor
  331. //
  332. //-------------------------------------------------------------------------
  333. nsBaseWidget::~nsBaseWidget()
  334. {
  335. IMEStateManager::WidgetDestroyed(this);
  336. if (mLayerManager) {
  337. if (BasicLayerManager* mgr = mLayerManager->AsBasicLayerManager()) {
  338. mgr->ClearRetainerWidget();
  339. }
  340. }
  341. FreeShutdownObserver();
  342. RevokeTransactionIdAllocator();
  343. DestroyLayerManager();
  344. #ifdef NOISY_WIDGET_LEAKS
  345. gNumWidgets--;
  346. printf("WIDGETS- = %d\n", gNumWidgets);
  347. #endif
  348. delete mOriginalBounds;
  349. }
  350. //-------------------------------------------------------------------------
  351. //
  352. // Basic create.
  353. //
  354. //-------------------------------------------------------------------------
  355. void nsBaseWidget::BaseCreate(nsIWidget* aParent,
  356. nsWidgetInitData* aInitData)
  357. {
  358. static bool gDisableNativeThemeCached = false;
  359. if (!gDisableNativeThemeCached) {
  360. Preferences::AddBoolVarCache(&gDisableNativeTheme,
  361. "mozilla.widget.disable-native-theme",
  362. gDisableNativeTheme);
  363. gDisableNativeThemeCached = true;
  364. }
  365. // keep a reference to the device context
  366. if (nullptr != aInitData) {
  367. mWindowType = aInitData->mWindowType;
  368. mBorderStyle = aInitData->mBorderStyle;
  369. mPopupLevel = aInitData->mPopupLevel;
  370. mPopupType = aInitData->mPopupHint;
  371. }
  372. if (aParent) {
  373. aParent->AddChild(this);
  374. }
  375. }
  376. //-------------------------------------------------------------------------
  377. //
  378. // Accessor functions to get/set the client data
  379. //
  380. //-------------------------------------------------------------------------
  381. nsIWidgetListener* nsBaseWidget::GetWidgetListener()
  382. {
  383. return mWidgetListener;
  384. }
  385. void nsBaseWidget::SetWidgetListener(nsIWidgetListener* aWidgetListener)
  386. {
  387. mWidgetListener = aWidgetListener;
  388. }
  389. already_AddRefed<nsIWidget>
  390. nsBaseWidget::CreateChild(const LayoutDeviceIntRect& aRect,
  391. nsWidgetInitData* aInitData,
  392. bool aForceUseIWidgetParent)
  393. {
  394. nsIWidget* parent = this;
  395. nsNativeWidget nativeParent = nullptr;
  396. if (!aForceUseIWidgetParent) {
  397. // Use only either parent or nativeParent, not both, to match
  398. // existing code. Eventually Create() should be divested of its
  399. // nativeWidget parameter.
  400. nativeParent = parent ? parent->GetNativeData(NS_NATIVE_WIDGET) : nullptr;
  401. parent = nativeParent ? nullptr : parent;
  402. MOZ_ASSERT(!parent || !nativeParent, "messed up logic");
  403. }
  404. nsCOMPtr<nsIWidget> widget;
  405. if (aInitData && aInitData->mWindowType == eWindowType_popup) {
  406. widget = AllocateChildPopupWidget();
  407. } else {
  408. static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID);
  409. widget = do_CreateInstance(kCChildCID);
  410. }
  411. if (widget &&
  412. NS_SUCCEEDED(widget->Create(parent, nativeParent, aRect, aInitData))) {
  413. return widget.forget();
  414. }
  415. return nullptr;
  416. }
  417. // Attach a view to our widget which we'll send events to.
  418. void
  419. nsBaseWidget::AttachViewToTopLevel(bool aUseAttachedEvents)
  420. {
  421. NS_ASSERTION((mWindowType == eWindowType_toplevel ||
  422. mWindowType == eWindowType_dialog ||
  423. mWindowType == eWindowType_invisible ||
  424. mWindowType == eWindowType_child),
  425. "Can't attach to window of that type");
  426. mUseAttachedEvents = aUseAttachedEvents;
  427. }
  428. nsIWidgetListener* nsBaseWidget::GetAttachedWidgetListener()
  429. {
  430. return mAttachedWidgetListener;
  431. }
  432. nsIWidgetListener* nsBaseWidget::GetPreviouslyAttachedWidgetListener()
  433. {
  434. return mPreviouslyAttachedWidgetListener;
  435. }
  436. void nsBaseWidget::SetPreviouslyAttachedWidgetListener(nsIWidgetListener* aListener)
  437. {
  438. mPreviouslyAttachedWidgetListener = aListener;
  439. }
  440. void nsBaseWidget::SetAttachedWidgetListener(nsIWidgetListener* aListener)
  441. {
  442. mAttachedWidgetListener = aListener;
  443. }
  444. //-------------------------------------------------------------------------
  445. //
  446. // Close this nsBaseWidget
  447. //
  448. //-------------------------------------------------------------------------
  449. void nsBaseWidget::Destroy()
  450. {
  451. // Just in case our parent is the only ref to us
  452. nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
  453. // disconnect from the parent
  454. nsIWidget *parent = GetParent();
  455. if (parent) {
  456. parent->RemoveChild(this);
  457. }
  458. #if defined(XP_WIN)
  459. // Allow our scroll capture container to be cleaned up, if we have one.
  460. mScrollCaptureContainer = nullptr;
  461. #endif
  462. }
  463. //-------------------------------------------------------------------------
  464. //
  465. // Set this nsBaseWidget's parent
  466. //
  467. //-------------------------------------------------------------------------
  468. NS_IMETHODIMP nsBaseWidget::SetParent(nsIWidget* aNewParent)
  469. {
  470. return NS_ERROR_NOT_IMPLEMENTED;
  471. }
  472. //-------------------------------------------------------------------------
  473. //
  474. // Get this nsBaseWidget parent
  475. //
  476. //-------------------------------------------------------------------------
  477. nsIWidget* nsBaseWidget::GetParent(void)
  478. {
  479. return nullptr;
  480. }
  481. //-------------------------------------------------------------------------
  482. //
  483. // Get this nsBaseWidget top level widget
  484. //
  485. //-------------------------------------------------------------------------
  486. nsIWidget* nsBaseWidget::GetTopLevelWidget()
  487. {
  488. nsIWidget *topLevelWidget = nullptr, *widget = this;
  489. while (widget) {
  490. topLevelWidget = widget;
  491. widget = widget->GetParent();
  492. }
  493. return topLevelWidget;
  494. }
  495. //-------------------------------------------------------------------------
  496. //
  497. // Get this nsBaseWidget's top (non-sheet) parent (if it's a sheet)
  498. //
  499. //-------------------------------------------------------------------------
  500. nsIWidget* nsBaseWidget::GetSheetWindowParent(void)
  501. {
  502. return nullptr;
  503. }
  504. float nsBaseWidget::GetDPI()
  505. {
  506. return 96.0f;
  507. }
  508. CSSToLayoutDeviceScale nsIWidget::GetDefaultScale()
  509. {
  510. double devPixelsPerCSSPixel = DefaultScaleOverride();
  511. if (devPixelsPerCSSPixel <= 0.0) {
  512. devPixelsPerCSSPixel = GetDefaultScaleInternal();
  513. }
  514. return CSSToLayoutDeviceScale(devPixelsPerCSSPixel);
  515. }
  516. /* static */
  517. double nsIWidget::DefaultScaleOverride()
  518. {
  519. // The number of device pixels per CSS pixel. A value <= 0 means choose
  520. // automatically based on the DPI. A positive value is used as-is. This effectively
  521. // controls the size of a CSS "px".
  522. double devPixelsPerCSSPixel = -1.0;
  523. nsAdoptingCString prefString = Preferences::GetCString("layout.css.devPixelsPerPx");
  524. if (!prefString.IsEmpty()) {
  525. devPixelsPerCSSPixel = PR_strtod(prefString, nullptr);
  526. }
  527. return devPixelsPerCSSPixel;
  528. }
  529. //-------------------------------------------------------------------------
  530. //
  531. // Add a child to the list of children
  532. //
  533. //-------------------------------------------------------------------------
  534. void nsBaseWidget::AddChild(nsIWidget* aChild)
  535. {
  536. MOZ_ASSERT(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
  537. "aChild not properly removed from its old child list");
  538. if (!mFirstChild) {
  539. mFirstChild = mLastChild = aChild;
  540. } else {
  541. // append to the list
  542. MOZ_ASSERT(mLastChild);
  543. MOZ_ASSERT(!mLastChild->GetNextSibling());
  544. mLastChild->SetNextSibling(aChild);
  545. aChild->SetPrevSibling(mLastChild);
  546. mLastChild = aChild;
  547. }
  548. }
  549. //-------------------------------------------------------------------------
  550. //
  551. // Remove a child from the list of children
  552. //
  553. //-------------------------------------------------------------------------
  554. void nsBaseWidget::RemoveChild(nsIWidget* aChild)
  555. {
  556. #ifdef DEBUG
  557. MOZ_RELEASE_ASSERT(aChild->GetParent() == this, "Not one of our kids!");
  558. #endif
  559. if (mLastChild == aChild) {
  560. mLastChild = mLastChild->GetPrevSibling();
  561. }
  562. if (mFirstChild == aChild) {
  563. mFirstChild = mFirstChild->GetNextSibling();
  564. }
  565. // Now remove from the list. Make sure that we pass ownership of the tail
  566. // of the list correctly before we have aChild let go of it.
  567. nsIWidget* prev = aChild->GetPrevSibling();
  568. nsIWidget* next = aChild->GetNextSibling();
  569. if (prev) {
  570. prev->SetNextSibling(next);
  571. }
  572. if (next) {
  573. next->SetPrevSibling(prev);
  574. }
  575. aChild->SetNextSibling(nullptr);
  576. aChild->SetPrevSibling(nullptr);
  577. }
  578. //-------------------------------------------------------------------------
  579. //
  580. // Sets widget's position within its parent's child list.
  581. //
  582. //-------------------------------------------------------------------------
  583. void nsBaseWidget::SetZIndex(int32_t aZIndex)
  584. {
  585. // Hold a ref to ourselves just in case, since we're going to remove
  586. // from our parent.
  587. nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
  588. mZIndex = aZIndex;
  589. // reorder this child in its parent's list.
  590. nsBaseWidget* parent = static_cast<nsBaseWidget*>(GetParent());
  591. if (parent) {
  592. parent->RemoveChild(this);
  593. // Scope sib outside the for loop so we can check it afterward
  594. nsIWidget* sib = parent->GetFirstChild();
  595. for ( ; sib; sib = sib->GetNextSibling()) {
  596. int32_t childZIndex = GetZIndex();
  597. if (aZIndex < childZIndex) {
  598. // Insert ourselves before sib
  599. nsIWidget* prev = sib->GetPrevSibling();
  600. mNextSibling = sib;
  601. mPrevSibling = prev;
  602. sib->SetPrevSibling(this);
  603. if (prev) {
  604. prev->SetNextSibling(this);
  605. } else {
  606. NS_ASSERTION(sib == parent->mFirstChild, "Broken child list");
  607. // We've taken ownership of sib, so it's safe to have parent let
  608. // go of it
  609. parent->mFirstChild = this;
  610. }
  611. PlaceBehind(eZPlacementBelow, sib, false);
  612. break;
  613. }
  614. }
  615. // were we added to the list?
  616. if (!sib) {
  617. parent->AddChild(this);
  618. }
  619. }
  620. }
  621. //-------------------------------------------------------------------------
  622. //
  623. // Maximize, minimize or restore the window. The BaseWidget implementation
  624. // merely stores the state.
  625. //
  626. //-------------------------------------------------------------------------
  627. void
  628. nsBaseWidget::SetSizeMode(nsSizeMode aMode)
  629. {
  630. MOZ_ASSERT(aMode == nsSizeMode_Normal ||
  631. aMode == nsSizeMode_Minimized ||
  632. aMode == nsSizeMode_Maximized ||
  633. aMode == nsSizeMode_Fullscreen);
  634. mSizeMode = aMode;
  635. }
  636. //-------------------------------------------------------------------------
  637. //
  638. // Get this component cursor
  639. //
  640. //-------------------------------------------------------------------------
  641. nsCursor nsBaseWidget::GetCursor()
  642. {
  643. return mCursor;
  644. }
  645. NS_IMETHODIMP nsBaseWidget::SetCursor(nsCursor aCursor)
  646. {
  647. mCursor = aCursor;
  648. return NS_OK;
  649. }
  650. NS_IMETHODIMP nsBaseWidget::SetCursor(imgIContainer* aCursor,
  651. uint32_t aHotspotX, uint32_t aHotspotY)
  652. {
  653. return NS_ERROR_NOT_IMPLEMENTED;
  654. }
  655. //-------------------------------------------------------------------------
  656. //
  657. // Window transparency methods
  658. //
  659. //-------------------------------------------------------------------------
  660. void nsBaseWidget::SetTransparencyMode(nsTransparencyMode aMode) {
  661. }
  662. nsTransparencyMode nsBaseWidget::GetTransparencyMode() {
  663. return eTransparencyOpaque;
  664. }
  665. bool
  666. nsBaseWidget::IsWindowClipRegionEqual(const nsTArray<LayoutDeviceIntRect>& aRects)
  667. {
  668. return mClipRects &&
  669. mClipRectCount == aRects.Length() &&
  670. memcmp(mClipRects.get(), aRects.Elements(), sizeof(LayoutDeviceIntRect)*mClipRectCount) == 0;
  671. }
  672. void
  673. nsBaseWidget::StoreWindowClipRegion(const nsTArray<LayoutDeviceIntRect>& aRects)
  674. {
  675. mClipRectCount = aRects.Length();
  676. mClipRects = MakeUnique<LayoutDeviceIntRect[]>(mClipRectCount);
  677. if (mClipRects) {
  678. memcpy(mClipRects.get(), aRects.Elements(), sizeof(LayoutDeviceIntRect)*mClipRectCount);
  679. }
  680. }
  681. void
  682. nsBaseWidget::GetWindowClipRegion(nsTArray<LayoutDeviceIntRect>* aRects)
  683. {
  684. if (mClipRects) {
  685. aRects->AppendElements(mClipRects.get(), mClipRectCount);
  686. } else {
  687. aRects->AppendElement(LayoutDeviceIntRect(0, 0, mBounds.width, mBounds.height));
  688. }
  689. }
  690. const LayoutDeviceIntRegion
  691. nsBaseWidget::RegionFromArray(const nsTArray<LayoutDeviceIntRect>& aRects)
  692. {
  693. LayoutDeviceIntRegion region;
  694. for (uint32_t i = 0; i < aRects.Length(); ++i) {
  695. region.Or(region, aRects[i]);
  696. }
  697. return region;
  698. }
  699. void
  700. nsBaseWidget::ArrayFromRegion(const LayoutDeviceIntRegion& aRegion,
  701. nsTArray<LayoutDeviceIntRect>& aRects)
  702. {
  703. for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
  704. aRects.AppendElement(iter.Get());
  705. }
  706. }
  707. nsresult
  708. nsBaseWidget::SetWindowClipRegion(const nsTArray<LayoutDeviceIntRect>& aRects,
  709. bool aIntersectWithExisting)
  710. {
  711. if (!aIntersectWithExisting) {
  712. StoreWindowClipRegion(aRects);
  713. } else {
  714. // get current rects
  715. nsTArray<LayoutDeviceIntRect> currentRects;
  716. GetWindowClipRegion(&currentRects);
  717. // create region from them
  718. LayoutDeviceIntRegion currentRegion = RegionFromArray(currentRects);
  719. // create region from new rects
  720. LayoutDeviceIntRegion newRegion = RegionFromArray(aRects);
  721. // intersect regions
  722. LayoutDeviceIntRegion intersection;
  723. intersection.And(currentRegion, newRegion);
  724. // create int rect array from intersection
  725. nsTArray<LayoutDeviceIntRect> rects;
  726. ArrayFromRegion(intersection, rects);
  727. // store
  728. StoreWindowClipRegion(rects);
  729. }
  730. return NS_OK;
  731. }
  732. //-------------------------------------------------------------------------
  733. //
  734. // Hide window borders/decorations for this widget
  735. //
  736. //-------------------------------------------------------------------------
  737. NS_IMETHODIMP nsBaseWidget::HideWindowChrome(bool aShouldHide)
  738. {
  739. return NS_ERROR_NOT_IMPLEMENTED;
  740. }
  741. /* virtual */ void
  742. nsBaseWidget::PerformFullscreenTransition(FullscreenTransitionStage aStage,
  743. uint16_t aDuration,
  744. nsISupports* aData,
  745. nsIRunnable* aCallback)
  746. {
  747. MOZ_ASSERT_UNREACHABLE(
  748. "Should never call PerformFullscreenTransition on nsBaseWidget");
  749. }
  750. //-------------------------------------------------------------------------
  751. //
  752. // Put the window into full-screen mode
  753. //
  754. //-------------------------------------------------------------------------
  755. void
  756. nsBaseWidget::InfallibleMakeFullScreen(bool aFullScreen, nsIScreen* aScreen)
  757. {
  758. HideWindowChrome(aFullScreen);
  759. if (aFullScreen) {
  760. if (!mOriginalBounds) {
  761. mOriginalBounds = new LayoutDeviceIntRect();
  762. }
  763. *mOriginalBounds = GetScreenBounds();
  764. // Move to top-left corner of screen and size to the screen dimensions
  765. nsCOMPtr<nsIScreen> screen = aScreen;
  766. if (!screen) {
  767. screen = GetWidgetScreen();
  768. }
  769. if (screen) {
  770. int32_t left, top, width, height;
  771. if (NS_SUCCEEDED(screen->GetRectDisplayPix(&left, &top, &width, &height))) {
  772. Resize(left, top, width, height, true);
  773. }
  774. }
  775. } else if (mOriginalBounds) {
  776. if (BoundsUseDesktopPixels()) {
  777. DesktopRect deskRect = *mOriginalBounds / GetDesktopToDeviceScale();
  778. Resize(deskRect.x, deskRect.y, deskRect.width, deskRect.height, true);
  779. } else {
  780. Resize(mOriginalBounds->x, mOriginalBounds->y, mOriginalBounds->width,
  781. mOriginalBounds->height, true);
  782. }
  783. }
  784. }
  785. nsresult
  786. nsBaseWidget::MakeFullScreen(bool aFullScreen, nsIScreen* aScreen)
  787. {
  788. InfallibleMakeFullScreen(aFullScreen, aScreen);
  789. return NS_OK;
  790. }
  791. nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
  792. nsBaseWidget* aWidget, gfxContext* aTarget,
  793. BufferMode aDoubleBuffering, ScreenRotation aRotation)
  794. : mWidget(aWidget)
  795. {
  796. LayerManager* lm = mWidget->GetLayerManager();
  797. NS_ASSERTION(!lm || lm->GetBackendType() == LayersBackend::LAYERS_BASIC,
  798. "AutoLayerManagerSetup instantiated for non-basic layer backend!");
  799. if (lm) {
  800. mLayerManager = lm->AsBasicLayerManager();
  801. if (mLayerManager) {
  802. mLayerManager->SetDefaultTarget(aTarget);
  803. mLayerManager->SetDefaultTargetConfiguration(aDoubleBuffering, aRotation);
  804. }
  805. }
  806. }
  807. nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup()
  808. {
  809. if (mLayerManager) {
  810. mLayerManager->SetDefaultTarget(nullptr);
  811. mLayerManager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0);
  812. }
  813. }
  814. bool nsBaseWidget::IsSmallPopup() const
  815. {
  816. return mWindowType == eWindowType_popup && mPopupType != ePopupTypePanel;
  817. }
  818. bool
  819. nsBaseWidget::ComputeShouldAccelerate()
  820. {
  821. return gfx::gfxConfig::IsEnabled(gfx::Feature::HW_COMPOSITING) &&
  822. WidgetTypeSupportsAcceleration();
  823. }
  824. bool
  825. nsBaseWidget::UseAPZ()
  826. {
  827. return (gfxPlatform::AsyncPanZoomEnabled() &&
  828. (WindowType() == eWindowType_toplevel || WindowType() == eWindowType_child));
  829. }
  830. void nsBaseWidget::CreateCompositor()
  831. {
  832. LayoutDeviceIntRect rect = GetBounds();
  833. CreateCompositor(rect.width, rect.height);
  834. }
  835. already_AddRefed<GeckoContentController>
  836. nsBaseWidget::CreateRootContentController()
  837. {
  838. RefPtr<GeckoContentController> controller = new ChromeProcessController(this, mAPZEventState, mAPZC);
  839. return controller.forget();
  840. }
  841. void nsBaseWidget::ConfigureAPZCTreeManager()
  842. {
  843. MOZ_ASSERT(mAPZC);
  844. ConfigureAPZControllerThread();
  845. mAPZC->SetDPI(GetDPI());
  846. RefPtr<IAPZCTreeManager> treeManager = mAPZC; // for capture by the lambdas
  847. ContentReceivedInputBlockCallback callback(
  848. [treeManager](const ScrollableLayerGuid& aGuid,
  849. uint64_t aInputBlockId,
  850. bool aPreventDefault)
  851. {
  852. MOZ_ASSERT(NS_IsMainThread());
  853. APZThreadUtils::RunOnControllerThread(NewRunnableMethod
  854. <uint64_t, bool>(treeManager,
  855. &IAPZCTreeManager::ContentReceivedInputBlock,
  856. aInputBlockId,
  857. aPreventDefault));
  858. });
  859. mAPZEventState = new APZEventState(this, mozilla::Move(callback));
  860. mSetAllowedTouchBehaviorCallback = [treeManager](uint64_t aInputBlockId,
  861. const nsTArray<TouchBehaviorFlags>& aFlags)
  862. {
  863. MOZ_ASSERT(NS_IsMainThread());
  864. APZThreadUtils::RunOnControllerThread(NewRunnableMethod
  865. <uint64_t,
  866. StoreCopyPassByLRef<nsTArray<TouchBehaviorFlags>>>(treeManager,
  867. &IAPZCTreeManager::SetAllowedTouchBehavior,
  868. aInputBlockId, aFlags));
  869. };
  870. mRootContentController = CreateRootContentController();
  871. if (mRootContentController) {
  872. mCompositorSession->SetContentController(mRootContentController);
  873. }
  874. // When APZ is enabled, we can actually enable raw touch events because we
  875. // have code that can deal with them properly. If APZ is not enabled, this
  876. // function doesn't get called.
  877. if (Preferences::GetInt("dom.w3c_touch_events.enabled", 0) ||
  878. Preferences::GetBool("dom.w3c_pointer_events.enabled", false)) {
  879. RegisterTouchWindow();
  880. }
  881. }
  882. void nsBaseWidget::ConfigureAPZControllerThread()
  883. {
  884. // By default the controller thread is the main thread.
  885. APZThreadUtils::SetControllerThread(MessageLoop::current());
  886. }
  887. void
  888. nsBaseWidget::SetConfirmedTargetAPZC(uint64_t aInputBlockId,
  889. const nsTArray<ScrollableLayerGuid>& aTargets) const
  890. {
  891. APZThreadUtils::RunOnControllerThread(NewRunnableMethod
  892. <uint64_t, StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>(mAPZC,
  893. &IAPZCTreeManager::SetTargetAPZC,
  894. aInputBlockId, aTargets));
  895. }
  896. void
  897. nsBaseWidget::UpdateZoomConstraints(const uint32_t& aPresShellId,
  898. const FrameMetrics::ViewID& aViewId,
  899. const Maybe<ZoomConstraints>& aConstraints)
  900. {
  901. if (!mCompositorSession || !mAPZC) {
  902. if (mInitialZoomConstraints) {
  903. MOZ_ASSERT(mInitialZoomConstraints->mPresShellID == aPresShellId);
  904. MOZ_ASSERT(mInitialZoomConstraints->mViewID == aViewId);
  905. if (!aConstraints) {
  906. mInitialZoomConstraints.reset();
  907. }
  908. }
  909. if (aConstraints) {
  910. // We have some constraints, but the compositor and APZC aren't created yet.
  911. // Save these so we can use them later.
  912. mInitialZoomConstraints = Some(InitialZoomConstraints(aPresShellId, aViewId, aConstraints.ref()));
  913. }
  914. return;
  915. }
  916. uint64_t layersId = mCompositorSession->RootLayerTreeId();
  917. mAPZC->UpdateZoomConstraints(ScrollableLayerGuid(layersId, aPresShellId, aViewId),
  918. aConstraints);
  919. }
  920. bool
  921. nsBaseWidget::AsyncPanZoomEnabled() const
  922. {
  923. return !!mAPZC;
  924. }
  925. nsEventStatus
  926. nsBaseWidget::ProcessUntransformedAPZEvent(WidgetInputEvent* aEvent,
  927. const ScrollableLayerGuid& aGuid,
  928. uint64_t aInputBlockId,
  929. nsEventStatus aApzResponse)
  930. {
  931. MOZ_ASSERT(NS_IsMainThread());
  932. InputAPZContext context(aGuid, aInputBlockId, aApzResponse);
  933. // If this is an event that the APZ has targeted to an APZC in the root
  934. // process, apply that APZC's callback-transform before dispatching the
  935. // event. If the event is instead targeted to an APZC in the child process,
  936. // the transform will be applied in the child process before dispatching
  937. // the event there (see e.g. TabChild::RecvRealTouchEvent()).
  938. if (aGuid.mLayersId == mCompositorSession->RootLayerTreeId()) {
  939. APZCCallbackHelper::ApplyCallbackTransform(*aEvent, aGuid,
  940. GetDefaultScale());
  941. }
  942. // Make a copy of the original event for the APZCCallbackHelper helpers that
  943. // we call later, because the event passed to DispatchEvent can get mutated in
  944. // ways that we don't want (i.e. touch points can get stripped out).
  945. nsEventStatus status;
  946. UniquePtr<WidgetEvent> original(aEvent->Duplicate());
  947. DispatchEvent(aEvent, status);
  948. if (mAPZC && !context.WasRoutedToChildProcess() && aInputBlockId) {
  949. // EventStateManager did not route the event into the child process.
  950. // It's safe to communicate to APZ that the event has been processed.
  951. // TODO: Eventually we'll be able to move the SendSetTargetAPZCNotification
  952. // call into APZEventState::Process*Event() as well.
  953. if (WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent()) {
  954. if (touchEvent->mMessage == eTouchStart) {
  955. if (gfxPrefs::TouchActionEnabled()) {
  956. APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification(this,
  957. GetDocument(), *(original->AsTouchEvent()), aInputBlockId,
  958. mSetAllowedTouchBehaviorCallback);
  959. }
  960. APZCCallbackHelper::SendSetTargetAPZCNotification(this, GetDocument(),
  961. *(original->AsTouchEvent()), aGuid, aInputBlockId);
  962. }
  963. mAPZEventState->ProcessTouchEvent(*touchEvent, aGuid, aInputBlockId,
  964. aApzResponse, status);
  965. } else if (WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent()) {
  966. MOZ_ASSERT(wheelEvent->mFlags.mHandledByAPZ);
  967. APZCCallbackHelper::SendSetTargetAPZCNotification(this, GetDocument(),
  968. *(original->AsWheelEvent()), aGuid, aInputBlockId);
  969. if (wheelEvent->mCanTriggerSwipe) {
  970. ReportSwipeStarted(aInputBlockId, wheelEvent->TriggersSwipe());
  971. }
  972. mAPZEventState->ProcessWheelEvent(*wheelEvent, aGuid, aInputBlockId);
  973. } else if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
  974. MOZ_ASSERT(mouseEvent->mFlags.mHandledByAPZ);
  975. APZCCallbackHelper::SendSetTargetAPZCNotification(this, GetDocument(),
  976. *(original->AsMouseEvent()), aGuid, aInputBlockId);
  977. mAPZEventState->ProcessMouseEvent(*mouseEvent, aGuid, aInputBlockId);
  978. }
  979. }
  980. return status;
  981. }
  982. class DispatchWheelEventOnMainThread : public Runnable
  983. {
  984. public:
  985. DispatchWheelEventOnMainThread(const ScrollWheelInput& aWheelInput,
  986. nsBaseWidget* aWidget,
  987. nsEventStatus aAPZResult,
  988. uint64_t aInputBlockId,
  989. ScrollableLayerGuid aGuid)
  990. : mWheelInput(aWheelInput)
  991. , mWidget(aWidget)
  992. , mAPZResult(aAPZResult)
  993. , mInputBlockId(aInputBlockId)
  994. , mGuid(aGuid)
  995. {
  996. }
  997. NS_IMETHOD Run() override
  998. {
  999. WidgetWheelEvent wheelEvent = mWheelInput.ToWidgetWheelEvent(mWidget);
  1000. mWidget->ProcessUntransformedAPZEvent(&wheelEvent, mGuid, mInputBlockId, mAPZResult);
  1001. return NS_OK;
  1002. }
  1003. private:
  1004. ScrollWheelInput mWheelInput;
  1005. nsBaseWidget* mWidget;
  1006. nsEventStatus mAPZResult;
  1007. uint64_t mInputBlockId;
  1008. ScrollableLayerGuid mGuid;
  1009. };
  1010. class DispatchWheelInputOnControllerThread : public Runnable
  1011. {
  1012. public:
  1013. DispatchWheelInputOnControllerThread(const WidgetWheelEvent& aWheelEvent,
  1014. IAPZCTreeManager* aAPZC,
  1015. nsBaseWidget* aWidget)
  1016. : mMainMessageLoop(MessageLoop::current())
  1017. , mWheelInput(aWheelEvent)
  1018. , mAPZC(aAPZC)
  1019. , mWidget(aWidget)
  1020. , mInputBlockId(0)
  1021. {
  1022. }
  1023. NS_IMETHOD Run() override
  1024. {
  1025. nsEventStatus result = mAPZC->ReceiveInputEvent(mWheelInput, &mGuid, &mInputBlockId);
  1026. if (result == nsEventStatus_eConsumeNoDefault) {
  1027. return NS_OK;
  1028. }
  1029. RefPtr<Runnable> r = new DispatchWheelEventOnMainThread(mWheelInput, mWidget, result, mInputBlockId, mGuid);
  1030. mMainMessageLoop->PostTask(r.forget());
  1031. return NS_OK;
  1032. }
  1033. private:
  1034. MessageLoop* mMainMessageLoop;
  1035. ScrollWheelInput mWheelInput;
  1036. RefPtr<IAPZCTreeManager> mAPZC;
  1037. nsBaseWidget* mWidget;
  1038. uint64_t mInputBlockId;
  1039. ScrollableLayerGuid mGuid;
  1040. };
  1041. void
  1042. nsBaseWidget::DispatchTouchInput(MultiTouchInput& aInput)
  1043. {
  1044. MOZ_ASSERT(NS_IsMainThread());
  1045. if (mAPZC) {
  1046. MOZ_ASSERT(APZThreadUtils::IsControllerThread());
  1047. uint64_t inputBlockId = 0;
  1048. ScrollableLayerGuid guid;
  1049. nsEventStatus result = mAPZC->ReceiveInputEvent(aInput, &guid, &inputBlockId);
  1050. if (result == nsEventStatus_eConsumeNoDefault) {
  1051. return;
  1052. }
  1053. WidgetTouchEvent event = aInput.ToWidgetTouchEvent(this);
  1054. ProcessUntransformedAPZEvent(&event, guid, inputBlockId, result);
  1055. } else {
  1056. WidgetTouchEvent event = aInput.ToWidgetTouchEvent(this);
  1057. nsEventStatus status;
  1058. DispatchEvent(&event, status);
  1059. }
  1060. }
  1061. nsEventStatus
  1062. nsBaseWidget::DispatchInputEvent(WidgetInputEvent* aEvent)
  1063. {
  1064. MOZ_ASSERT(NS_IsMainThread());
  1065. if (mAPZC) {
  1066. if (APZThreadUtils::IsControllerThread()) {
  1067. uint64_t inputBlockId = 0;
  1068. ScrollableLayerGuid guid;
  1069. nsEventStatus result = mAPZC->ReceiveInputEvent(*aEvent, &guid, &inputBlockId);
  1070. if (result == nsEventStatus_eConsumeNoDefault) {
  1071. return result;
  1072. }
  1073. return ProcessUntransformedAPZEvent(aEvent, guid, inputBlockId, result);
  1074. } else {
  1075. WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent();
  1076. if (wheelEvent) {
  1077. RefPtr<Runnable> r = new DispatchWheelInputOnControllerThread(*wheelEvent, mAPZC, this);
  1078. APZThreadUtils::RunOnControllerThread(r.forget());
  1079. return nsEventStatus_eConsumeDoDefault;
  1080. }
  1081. MOZ_CRASH();
  1082. }
  1083. }
  1084. nsEventStatus status;
  1085. DispatchEvent(aEvent, status);
  1086. return status;
  1087. }
  1088. void
  1089. nsBaseWidget::DispatchEventToAPZOnly(mozilla::WidgetInputEvent* aEvent)
  1090. {
  1091. MOZ_ASSERT(NS_IsMainThread());
  1092. if (mAPZC) {
  1093. MOZ_ASSERT(APZThreadUtils::IsControllerThread());
  1094. uint64_t inputBlockId = 0;
  1095. ScrollableLayerGuid guid;
  1096. mAPZC->ReceiveInputEvent(*aEvent, &guid, &inputBlockId);
  1097. }
  1098. }
  1099. nsIDocument*
  1100. nsBaseWidget::GetDocument() const
  1101. {
  1102. if (mWidgetListener) {
  1103. if (nsIPresShell* presShell = mWidgetListener->GetPresShell()) {
  1104. return presShell->GetDocument();
  1105. }
  1106. }
  1107. return nullptr;
  1108. }
  1109. void nsBaseWidget::CreateCompositorVsyncDispatcher()
  1110. {
  1111. // Parent directly listens to the vsync source whereas
  1112. // child process communicate via IPC
  1113. // Should be called AFTER gfxPlatform is initialized
  1114. if (XRE_IsParentProcess()) {
  1115. mCompositorVsyncDispatcher = new CompositorVsyncDispatcher();
  1116. }
  1117. }
  1118. CompositorVsyncDispatcher*
  1119. nsBaseWidget::GetCompositorVsyncDispatcher()
  1120. {
  1121. return mCompositorVsyncDispatcher;
  1122. }
  1123. void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
  1124. {
  1125. // This makes sure that gfxPlatforms gets initialized if it hasn't by now.
  1126. gfxPlatform::GetPlatform();
  1127. MOZ_ASSERT(gfxPlatform::UsesOffMainThreadCompositing(),
  1128. "This function assumes OMTC");
  1129. MOZ_ASSERT(!mCompositorSession && !mCompositorBridgeChild,
  1130. "Should have properly cleaned up the previous PCompositor pair beforehand");
  1131. if (mCompositorBridgeChild) {
  1132. mCompositorBridgeChild->Destroy();
  1133. }
  1134. // Recreating this is tricky, as we may still have an old and we need
  1135. // to make sure it's properly destroyed by calling DestroyCompositor!
  1136. // If we've already received a shutdown notification, don't try
  1137. // create a new compositor.
  1138. if (!mShutdownObserver) {
  1139. return;
  1140. }
  1141. CreateCompositorVsyncDispatcher();
  1142. RefPtr<ClientLayerManager> lm = new ClientLayerManager(this);
  1143. bool useAPZ = UseAPZ();
  1144. gfx::GPUProcessManager* gpu = gfx::GPUProcessManager::Get();
  1145. mCompositorSession = gpu->CreateTopLevelCompositor(
  1146. this,
  1147. lm,
  1148. GetDefaultScale(),
  1149. useAPZ,
  1150. UseExternalCompositingSurface(),
  1151. gfx::IntSize(aWidth, aHeight));
  1152. mCompositorBridgeChild = mCompositorSession->GetCompositorBridgeChild();
  1153. mCompositorWidgetDelegate = mCompositorSession->GetCompositorWidgetDelegate();
  1154. if (useAPZ) {
  1155. mAPZC = mCompositorSession->GetAPZCTreeManager();
  1156. ConfigureAPZCTreeManager();
  1157. } else {
  1158. mAPZC = nullptr;
  1159. }
  1160. if (mInitialZoomConstraints) {
  1161. UpdateZoomConstraints(mInitialZoomConstraints->mPresShellID,
  1162. mInitialZoomConstraints->mViewID,
  1163. Some(mInitialZoomConstraints->mConstraints));
  1164. mInitialZoomConstraints.reset();
  1165. }
  1166. ShadowLayerForwarder* lf = lm->AsShadowForwarder();
  1167. // As long as we are creating a ClientLayerManager above lf must be non-null.
  1168. MOZ_ASSERT(lf);
  1169. if (lf) {
  1170. TextureFactoryIdentifier textureFactoryIdentifier;
  1171. PLayerTransactionChild* shadowManager = nullptr;
  1172. nsTArray<LayersBackend> backendHints;
  1173. gfxPlatform::GetPlatform()->GetCompositorBackends(ComputeShouldAccelerate(), backendHints);
  1174. bool success = false;
  1175. if (!backendHints.IsEmpty()) {
  1176. shadowManager = mCompositorBridgeChild->SendPLayerTransactionConstructor(
  1177. backendHints, 0, &textureFactoryIdentifier, &success);
  1178. }
  1179. if (!success) {
  1180. NS_WARNING("Failed to create an OMT compositor.");
  1181. DestroyCompositor();
  1182. mLayerManager = nullptr;
  1183. return;
  1184. }
  1185. lf->SetShadowManager(shadowManager);
  1186. if (ClientLayerManager* clm = lm->AsClientLayerManager()) {
  1187. clm->UpdateTextureFactoryIdentifier(textureFactoryIdentifier);
  1188. }
  1189. // Some popup or transparent widgets may use a different backend than the
  1190. // compositors used with ImageBridge and VR (and more generally web content).
  1191. if (WidgetTypeSupportsAcceleration()) {
  1192. ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
  1193. }
  1194. }
  1195. WindowUsesOMTC();
  1196. mLayerManager = lm.forget();
  1197. // Only track compositors for top-level windows, since other window types
  1198. // may use the basic compositor.
  1199. bool getCompositorFromThisWindow = (mWindowType == eWindowType_toplevel);
  1200. if (getCompositorFromThisWindow) {
  1201. gfxPlatform::GetPlatform()->NotifyCompositorCreated(mLayerManager->GetCompositorBackendType());
  1202. }
  1203. }
  1204. void nsBaseWidget::NotifyRemoteCompositorSessionLost(CompositorSession* aSession)
  1205. {
  1206. MOZ_ASSERT(aSession == mCompositorSession);
  1207. DestroyLayerManager();
  1208. }
  1209. bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
  1210. {
  1211. return gfxPlatform::UsesOffMainThreadCompositing();
  1212. }
  1213. LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
  1214. LayersBackend aBackendHint,
  1215. LayerManagerPersistence aPersistence)
  1216. {
  1217. if (!mLayerManager) {
  1218. if (!mShutdownObserver) {
  1219. // We are shutting down, do not try to re-create a LayerManager
  1220. return nullptr;
  1221. }
  1222. // Try to use an async compositor first, if possible
  1223. if (ShouldUseOffMainThreadCompositing()) {
  1224. // e10s uses the parameter to pass in the shadow manager from the TabChild
  1225. // so we don't expect to see it there since this doesn't support e10s.
  1226. NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s");
  1227. CreateCompositor();
  1228. }
  1229. if (!mLayerManager) {
  1230. mLayerManager = CreateBasicLayerManager();
  1231. }
  1232. }
  1233. return mLayerManager;
  1234. }
  1235. LayerManager* nsBaseWidget::CreateBasicLayerManager()
  1236. {
  1237. return new BasicLayerManager(this);
  1238. }
  1239. CompositorBridgeChild* nsBaseWidget::GetRemoteRenderer()
  1240. {
  1241. return mCompositorBridgeChild;
  1242. }
  1243. already_AddRefed<gfx::DrawTarget>
  1244. nsBaseWidget::StartRemoteDrawing()
  1245. {
  1246. return nullptr;
  1247. }
  1248. uint32_t
  1249. nsBaseWidget::GetGLFrameBufferFormat()
  1250. {
  1251. return LOCAL_GL_RGBA;
  1252. }
  1253. //-------------------------------------------------------------------------
  1254. //
  1255. // Destroy the window
  1256. //
  1257. //-------------------------------------------------------------------------
  1258. void nsBaseWidget::OnDestroy()
  1259. {
  1260. if (mTextEventDispatcher) {
  1261. mTextEventDispatcher->OnDestroyWidget();
  1262. // Don't release it until this widget actually released because after this
  1263. // is called, TextEventDispatcher() may create it again.
  1264. }
  1265. // If this widget is being destroyed, let the APZ code know to drop references
  1266. // to this widget. Callers of this function all should be holding a deathgrip
  1267. // on this widget already.
  1268. ReleaseContentController();
  1269. }
  1270. NS_IMETHODIMP nsBaseWidget::MoveClient(double aX, double aY)
  1271. {
  1272. LayoutDeviceIntPoint clientOffset(GetClientOffset());
  1273. // GetClientOffset returns device pixels; scale back to desktop pixels
  1274. // if that's what this widget uses for the Move/Resize APIs
  1275. if (BoundsUseDesktopPixels()) {
  1276. DesktopPoint desktopOffset = clientOffset / GetDesktopToDeviceScale();
  1277. return Move(aX - desktopOffset.x, aY - desktopOffset.y);
  1278. } else {
  1279. return Move(aX - clientOffset.x, aY - clientOffset.y);
  1280. }
  1281. }
  1282. NS_IMETHODIMP nsBaseWidget::ResizeClient(double aWidth,
  1283. double aHeight,
  1284. bool aRepaint)
  1285. {
  1286. NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
  1287. NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
  1288. LayoutDeviceIntRect clientBounds = GetClientBounds();
  1289. // GetClientBounds and mBounds are device pixels; scale back to desktop pixels
  1290. // if that's what this widget uses for the Move/Resize APIs
  1291. if (BoundsUseDesktopPixels()) {
  1292. DesktopSize desktopDelta =
  1293. (LayoutDeviceIntSize(mBounds.width, mBounds.height) -
  1294. clientBounds.Size()) / GetDesktopToDeviceScale();
  1295. return Resize(aWidth + desktopDelta.width, aHeight + desktopDelta.height,
  1296. aRepaint);
  1297. } else {
  1298. return Resize(mBounds.width + (aWidth - clientBounds.width),
  1299. mBounds.height + (aHeight - clientBounds.height), aRepaint);
  1300. }
  1301. }
  1302. NS_IMETHODIMP nsBaseWidget::ResizeClient(double aX,
  1303. double aY,
  1304. double aWidth,
  1305. double aHeight,
  1306. bool aRepaint)
  1307. {
  1308. NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
  1309. NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
  1310. LayoutDeviceIntRect clientBounds = GetClientBounds();
  1311. LayoutDeviceIntPoint clientOffset = GetClientOffset();
  1312. if (BoundsUseDesktopPixels()) {
  1313. DesktopToLayoutDeviceScale scale = GetDesktopToDeviceScale();
  1314. DesktopPoint desktopOffset = clientOffset / scale;
  1315. DesktopSize desktopDelta =
  1316. (LayoutDeviceIntSize(mBounds.width, mBounds.height) -
  1317. clientBounds.Size()) / scale;
  1318. return Resize(aX - desktopOffset.x, aY - desktopOffset.y,
  1319. aWidth + desktopDelta.width, aHeight + desktopDelta.height,
  1320. aRepaint);
  1321. } else {
  1322. return Resize(aX - clientOffset.x, aY - clientOffset.y,
  1323. aWidth + mBounds.width - clientBounds.width,
  1324. aHeight + mBounds.height - clientBounds.height,
  1325. aRepaint);
  1326. }
  1327. }
  1328. //-------------------------------------------------------------------------
  1329. //
  1330. // Bounds
  1331. //
  1332. //-------------------------------------------------------------------------
  1333. /**
  1334. * If the implementation of nsWindow supports borders this method MUST be overridden
  1335. *
  1336. **/
  1337. LayoutDeviceIntRect
  1338. nsBaseWidget::GetClientBounds()
  1339. {
  1340. return GetBounds();
  1341. }
  1342. /**
  1343. * If the implementation of nsWindow supports borders this method MUST be overridden
  1344. *
  1345. **/
  1346. LayoutDeviceIntRect
  1347. nsBaseWidget::GetBounds()
  1348. {
  1349. return mBounds;
  1350. }
  1351. /**
  1352. * If the implementation of nsWindow uses a local coordinate system within the window,
  1353. * this method must be overridden
  1354. *
  1355. **/
  1356. LayoutDeviceIntRect
  1357. nsBaseWidget::GetScreenBounds()
  1358. {
  1359. return GetBounds();
  1360. }
  1361. nsresult
  1362. nsBaseWidget::GetRestoredBounds(LayoutDeviceIntRect& aRect)
  1363. {
  1364. if (SizeMode() != nsSizeMode_Normal) {
  1365. return NS_ERROR_FAILURE;
  1366. }
  1367. aRect = GetScreenBounds();
  1368. return NS_OK;
  1369. }
  1370. LayoutDeviceIntPoint
  1371. nsBaseWidget::GetClientOffset()
  1372. {
  1373. return LayoutDeviceIntPoint(0, 0);
  1374. }
  1375. NS_IMETHODIMP
  1376. nsBaseWidget::SetNonClientMargins(LayoutDeviceIntMargin &margins)
  1377. {
  1378. return NS_ERROR_NOT_IMPLEMENTED;
  1379. }
  1380. uint32_t nsBaseWidget::GetMaxTouchPoints() const
  1381. {
  1382. return 0;
  1383. }
  1384. NS_IMETHODIMP
  1385. nsBaseWidget::GetAttention(int32_t aCycleCount) {
  1386. return NS_OK;
  1387. }
  1388. bool
  1389. nsBaseWidget::HasPendingInputEvent()
  1390. {
  1391. return false;
  1392. }
  1393. NS_IMETHODIMP
  1394. nsBaseWidget::SetIcon(const nsAString&)
  1395. {
  1396. return NS_OK;
  1397. }
  1398. bool
  1399. nsBaseWidget::ShowsResizeIndicator(LayoutDeviceIntRect* aResizerRect)
  1400. {
  1401. return false;
  1402. }
  1403. /**
  1404. * Modifies aFile to point at an icon file with the given name and suffix. The
  1405. * suffix may correspond to a file extension with leading '.' if appropriate.
  1406. * Returns true if the icon file exists and can be read.
  1407. */
  1408. static bool
  1409. ResolveIconNameHelper(nsIFile *aFile,
  1410. const nsAString &aIconName,
  1411. const nsAString &aIconSuffix)
  1412. {
  1413. aFile->Append(NS_LITERAL_STRING("icons"));
  1414. aFile->Append(NS_LITERAL_STRING("default"));
  1415. aFile->Append(aIconName + aIconSuffix);
  1416. bool readable;
  1417. return NS_SUCCEEDED(aFile->IsReadable(&readable)) && readable;
  1418. }
  1419. /**
  1420. * Resolve the given icon name into a local file object. This method is
  1421. * intended to be called by subclasses of nsBaseWidget. aIconSuffix is a
  1422. * platform specific icon file suffix (e.g., ".ico" under Win32).
  1423. *
  1424. * If no file is found matching the given parameters, then null is returned.
  1425. */
  1426. void
  1427. nsBaseWidget::ResolveIconName(const nsAString &aIconName,
  1428. const nsAString &aIconSuffix,
  1429. nsIFile **aResult)
  1430. {
  1431. *aResult = nullptr;
  1432. nsCOMPtr<nsIProperties> dirSvc = do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
  1433. if (!dirSvc)
  1434. return;
  1435. // first check auxilary chrome directories
  1436. nsCOMPtr<nsISimpleEnumerator> dirs;
  1437. dirSvc->Get(NS_APP_CHROME_DIR_LIST, NS_GET_IID(nsISimpleEnumerator),
  1438. getter_AddRefs(dirs));
  1439. if (dirs) {
  1440. bool hasMore;
  1441. while (NS_SUCCEEDED(dirs->HasMoreElements(&hasMore)) && hasMore) {
  1442. nsCOMPtr<nsISupports> element;
  1443. dirs->GetNext(getter_AddRefs(element));
  1444. if (!element)
  1445. continue;
  1446. nsCOMPtr<nsIFile> file = do_QueryInterface(element);
  1447. if (!file)
  1448. continue;
  1449. if (ResolveIconNameHelper(file, aIconName, aIconSuffix)) {
  1450. NS_ADDREF(*aResult = file);
  1451. return;
  1452. }
  1453. }
  1454. }
  1455. // then check the main app chrome directory
  1456. nsCOMPtr<nsIFile> file;
  1457. dirSvc->Get(NS_APP_CHROME_DIR, NS_GET_IID(nsIFile),
  1458. getter_AddRefs(file));
  1459. if (file && ResolveIconNameHelper(file, aIconName, aIconSuffix))
  1460. NS_ADDREF(*aResult = file);
  1461. }
  1462. NS_IMETHODIMP
  1463. nsBaseWidget::BeginResizeDrag(WidgetGUIEvent* aEvent,
  1464. int32_t aHorizontal,
  1465. int32_t aVertical)
  1466. {
  1467. return NS_ERROR_NOT_IMPLEMENTED;
  1468. }
  1469. NS_IMETHODIMP
  1470. nsBaseWidget::BeginMoveDrag(WidgetMouseEvent* aEvent)
  1471. {
  1472. return NS_ERROR_NOT_IMPLEMENTED;
  1473. }
  1474. void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints)
  1475. {
  1476. mSizeConstraints = aConstraints;
  1477. // We can't ensure that the size is honored at this point because we're
  1478. // probably in the middle of a reflow.
  1479. }
  1480. const widget::SizeConstraints nsBaseWidget::GetSizeConstraints()
  1481. {
  1482. return mSizeConstraints;
  1483. }
  1484. // static
  1485. nsIRollupListener*
  1486. nsBaseWidget::GetActiveRollupListener()
  1487. {
  1488. // If set, then this is likely an <html:select> dropdown.
  1489. if (gRollupListener)
  1490. return gRollupListener;
  1491. return nsXULPopupManager::GetInstance();
  1492. }
  1493. void
  1494. nsBaseWidget::NotifyWindowDestroyed()
  1495. {
  1496. if (!mWidgetListener)
  1497. return;
  1498. nsCOMPtr<nsIXULWindow> window = mWidgetListener->GetXULWindow();
  1499. nsCOMPtr<nsIBaseWindow> xulWindow(do_QueryInterface(window));
  1500. if (xulWindow) {
  1501. xulWindow->Destroy();
  1502. }
  1503. }
  1504. void
  1505. nsBaseWidget::NotifySizeMoveDone()
  1506. {
  1507. if (!mWidgetListener || mWidgetListener->GetXULWindow())
  1508. return;
  1509. nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1510. if (presShell) {
  1511. presShell->WindowSizeMoveDone();
  1512. }
  1513. }
  1514. void
  1515. nsBaseWidget::NotifyWindowMoved(int32_t aX, int32_t aY)
  1516. {
  1517. if (mWidgetListener) {
  1518. mWidgetListener->WindowMoved(this, aX, aY);
  1519. }
  1520. if (mIMEHasFocus && GetIMEUpdatePreference().WantPositionChanged()) {
  1521. NotifyIME(IMENotification(IMEMessage::NOTIFY_IME_OF_POSITION_CHANGE));
  1522. }
  1523. }
  1524. void
  1525. nsBaseWidget::NotifySysColorChanged()
  1526. {
  1527. if (!mWidgetListener || mWidgetListener->GetXULWindow())
  1528. return;
  1529. nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1530. if (presShell) {
  1531. presShell->SysColorChanged();
  1532. }
  1533. }
  1534. void
  1535. nsBaseWidget::NotifyThemeChanged()
  1536. {
  1537. if (!mWidgetListener || mWidgetListener->GetXULWindow())
  1538. return;
  1539. nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1540. if (presShell) {
  1541. presShell->ThemeChanged();
  1542. }
  1543. }
  1544. void
  1545. nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators,
  1546. UIStateChangeType aShowFocusRings)
  1547. {
  1548. if (nsIDocument* doc = GetDocument()) {
  1549. nsPIDOMWindowOuter* win = doc->GetWindow();
  1550. if (win) {
  1551. win->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings);
  1552. }
  1553. }
  1554. }
  1555. NS_IMETHODIMP
  1556. nsBaseWidget::NotifyIME(const IMENotification& aIMENotification)
  1557. {
  1558. switch (aIMENotification.mMessage) {
  1559. case REQUEST_TO_COMMIT_COMPOSITION:
  1560. case REQUEST_TO_CANCEL_COMPOSITION:
  1561. // Currently, if native IME handler doesn't use TextEventDispatcher,
  1562. // the request may be notified to mTextEventDispatcher or native IME
  1563. // directly. Therefore, if mTextEventDispatcher has a composition,
  1564. // the request should be handled by the mTextEventDispatcher.
  1565. if (mTextEventDispatcher && mTextEventDispatcher->IsComposing()) {
  1566. return mTextEventDispatcher->NotifyIME(aIMENotification);
  1567. }
  1568. // Otherwise, it should be handled by native IME.
  1569. return NotifyIMEInternal(aIMENotification);
  1570. default: {
  1571. if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
  1572. mIMEHasFocus = true;
  1573. }
  1574. EnsureTextEventDispatcher();
  1575. // If the platform specific widget uses TextEventDispatcher for handling
  1576. // native IME and keyboard events, IME event handler should be notified
  1577. // of the notification via TextEventDispatcher. Otherwise, on the other
  1578. // platforms which have not used TextEventDispatcher yet, IME event
  1579. // handler should be notified by the old path (NotifyIMEInternal).
  1580. nsresult rv = mTextEventDispatcher->NotifyIME(aIMENotification);
  1581. nsresult rv2 = NotifyIMEInternal(aIMENotification);
  1582. if (aIMENotification.mMessage == NOTIFY_IME_OF_BLUR) {
  1583. mIMEHasFocus = false;
  1584. }
  1585. return rv2 == NS_ERROR_NOT_IMPLEMENTED ? rv : rv2;
  1586. }
  1587. }
  1588. }
  1589. void
  1590. nsBaseWidget::EnsureTextEventDispatcher()
  1591. {
  1592. if (mTextEventDispatcher) {
  1593. return;
  1594. }
  1595. mTextEventDispatcher = new TextEventDispatcher(this);
  1596. }
  1597. NS_IMETHODIMP_(nsIWidget::TextEventDispatcher*)
  1598. nsBaseWidget::GetTextEventDispatcher()
  1599. {
  1600. EnsureTextEventDispatcher();
  1601. return mTextEventDispatcher;
  1602. }
  1603. void*
  1604. nsBaseWidget::GetPseudoIMEContext()
  1605. {
  1606. TextEventDispatcher* dispatcher = GetTextEventDispatcher();
  1607. if (!dispatcher) {
  1608. return nullptr;
  1609. }
  1610. return dispatcher->GetPseudoIMEContext();
  1611. }
  1612. NS_IMETHODIMP_(TextEventDispatcherListener*)
  1613. nsBaseWidget::GetNativeTextEventDispatcherListener()
  1614. {
  1615. // TODO: If all platforms supported use of TextEventDispatcher for handling
  1616. // native IME and keyboard events, this method should be removed since
  1617. // in such case, this is overridden by all the subclasses.
  1618. return nullptr;
  1619. }
  1620. void
  1621. nsBaseWidget::ZoomToRect(const uint32_t& aPresShellId,
  1622. const FrameMetrics::ViewID& aViewId,
  1623. const CSSRect& aRect,
  1624. const uint32_t& aFlags)
  1625. {
  1626. if (!mCompositorSession || !mAPZC) {
  1627. return;
  1628. }
  1629. uint64_t layerId = mCompositorSession->RootLayerTreeId();
  1630. mAPZC->ZoomToRect(ScrollableLayerGuid(layerId, aPresShellId, aViewId), aRect, aFlags);
  1631. }
  1632. #ifdef ACCESSIBILITY
  1633. #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
  1634. // defined in nsAppRunner.cpp
  1635. extern const char* kAccessibilityLastRunDatePref;
  1636. static inline uint32_t
  1637. PRTimeToSeconds(PRTime t_usec)
  1638. {
  1639. PRTime usec_per_sec = PR_USEC_PER_SEC;
  1640. return uint32_t(t_usec /= usec_per_sec);
  1641. }
  1642. #endif
  1643. a11y::Accessible*
  1644. nsBaseWidget::GetRootAccessible()
  1645. {
  1646. NS_ENSURE_TRUE(mWidgetListener, nullptr);
  1647. nsIPresShell* presShell = mWidgetListener->GetPresShell();
  1648. NS_ENSURE_TRUE(presShell, nullptr);
  1649. // If container is null then the presshell is not active. This often happens
  1650. // when a preshell is being held onto for fastback.
  1651. nsPresContext* presContext = presShell->GetPresContext();
  1652. NS_ENSURE_TRUE(presContext->GetContainerWeak(), nullptr);
  1653. // Accessible creation might be not safe so use IsSafeToRunScript to
  1654. // make sure it's not created at unsafe times.
  1655. nsAccessibilityService* accService = GetOrCreateAccService();
  1656. if (accService) {
  1657. #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
  1658. if (!mAccessibilityInUseFlag) {
  1659. mAccessibilityInUseFlag = true;
  1660. uint32_t now = PRTimeToSeconds(PR_Now());
  1661. Preferences::SetInt(kAccessibilityLastRunDatePref, now);
  1662. }
  1663. #endif
  1664. return accService->GetRootDocumentAccessible(presShell, nsContentUtils::IsSafeToRunScript());
  1665. }
  1666. return nullptr;
  1667. }
  1668. #endif // ACCESSIBILITY
  1669. void
  1670. nsBaseWidget::StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
  1671. {
  1672. if (!AsyncPanZoomEnabled()) {
  1673. return;
  1674. }
  1675. MOZ_ASSERT(XRE_IsParentProcess() && mCompositorSession);
  1676. int layersId = mCompositorSession->RootLayerTreeId();;
  1677. ScrollableLayerGuid guid(layersId, aDragMetrics.mPresShellId, aDragMetrics.mViewId);
  1678. APZThreadUtils::RunOnControllerThread(NewRunnableMethod
  1679. <ScrollableLayerGuid, AsyncDragMetrics>(mAPZC,
  1680. &IAPZCTreeManager::StartScrollbarDrag,
  1681. guid, aDragMetrics));
  1682. }
  1683. already_AddRefed<nsIScreen>
  1684. nsBaseWidget::GetWidgetScreen()
  1685. {
  1686. nsCOMPtr<nsIScreenManager> screenManager;
  1687. screenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
  1688. if (!screenManager) {
  1689. return nullptr;
  1690. }
  1691. LayoutDeviceIntRect bounds = GetScreenBounds();
  1692. DesktopIntRect deskBounds = RoundedToInt(bounds / GetDesktopToDeviceScale());
  1693. nsCOMPtr<nsIScreen> screen;
  1694. screenManager->ScreenForRect(deskBounds.x, deskBounds.y,
  1695. deskBounds.width, deskBounds.height,
  1696. getter_AddRefs(screen));
  1697. return screen.forget();
  1698. }
  1699. nsresult
  1700. nsIWidget::SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint, bool aLongTap,
  1701. nsIObserver* aObserver)
  1702. {
  1703. AutoObserverNotifier notifier(aObserver, "touchtap");
  1704. if (sPointerIdCounter > TOUCH_INJECT_MAX_POINTS) {
  1705. sPointerIdCounter = 0;
  1706. }
  1707. int pointerId = sPointerIdCounter;
  1708. sPointerIdCounter++;
  1709. nsresult rv = SynthesizeNativeTouchPoint(pointerId, TOUCH_CONTACT,
  1710. aPoint, 1.0, 90, nullptr);
  1711. if (NS_FAILED(rv)) {
  1712. return rv;
  1713. }
  1714. if (!aLongTap) {
  1715. return SynthesizeNativeTouchPoint(pointerId, TOUCH_REMOVE,
  1716. aPoint, 0, 0, nullptr);
  1717. }
  1718. // initiate a long tap
  1719. int elapse = Preferences::GetInt("ui.click_hold_context_menus.delay",
  1720. TOUCH_INJECT_LONG_TAP_DEFAULT_MSEC);
  1721. if (!mLongTapTimer) {
  1722. mLongTapTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
  1723. if (NS_FAILED(rv)) {
  1724. SynthesizeNativeTouchPoint(pointerId, TOUCH_CANCEL,
  1725. aPoint, 0, 0, nullptr);
  1726. return NS_ERROR_UNEXPECTED;
  1727. }
  1728. // Windows requires recuring events, so we set this to a smaller window
  1729. // than the pref value.
  1730. int timeout = elapse;
  1731. if (timeout > TOUCH_INJECT_PUMP_TIMER_MSEC) {
  1732. timeout = TOUCH_INJECT_PUMP_TIMER_MSEC;
  1733. }
  1734. mLongTapTimer->InitWithFuncCallback(OnLongTapTimerCallback, this,
  1735. timeout,
  1736. nsITimer::TYPE_REPEATING_SLACK);
  1737. }
  1738. // If we already have a long tap pending, cancel it. We only allow one long
  1739. // tap to be active at a time.
  1740. if (mLongTapTouchPoint) {
  1741. SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL,
  1742. mLongTapTouchPoint->mPosition, 0, 0, nullptr);
  1743. }
  1744. mLongTapTouchPoint =
  1745. MakeUnique<LongTapInfo>(pointerId, aPoint,
  1746. TimeDuration::FromMilliseconds(elapse),
  1747. aObserver);
  1748. notifier.SkipNotification(); // we'll do it in the long-tap callback
  1749. return NS_OK;
  1750. }
  1751. // static
  1752. void
  1753. nsIWidget::OnLongTapTimerCallback(nsITimer* aTimer, void* aClosure)
  1754. {
  1755. nsIWidget *self = static_cast<nsIWidget *>(aClosure);
  1756. if ((self->mLongTapTouchPoint->mStamp + self->mLongTapTouchPoint->mDuration) >
  1757. TimeStamp::Now()) {
  1758. #ifdef XP_WIN
  1759. // Windows needs us to keep pumping feedback to the digitizer, so update
  1760. // the pointer id with the same position.
  1761. self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId,
  1762. TOUCH_CONTACT,
  1763. self->mLongTapTouchPoint->mPosition,
  1764. 1.0, 90, nullptr);
  1765. #endif
  1766. return;
  1767. }
  1768. AutoObserverNotifier notifier(self->mLongTapTouchPoint->mObserver, "touchtap");
  1769. // finished, remove the touch point
  1770. self->mLongTapTimer->Cancel();
  1771. self->mLongTapTimer = nullptr;
  1772. self->SynthesizeNativeTouchPoint(self->mLongTapTouchPoint->mPointerId,
  1773. TOUCH_REMOVE,
  1774. self->mLongTapTouchPoint->mPosition,
  1775. 0, 0, nullptr);
  1776. self->mLongTapTouchPoint = nullptr;
  1777. }
  1778. nsresult
  1779. nsIWidget::ClearNativeTouchSequence(nsIObserver* aObserver)
  1780. {
  1781. AutoObserverNotifier notifier(aObserver, "cleartouch");
  1782. if (!mLongTapTimer) {
  1783. return NS_OK;
  1784. }
  1785. mLongTapTimer->Cancel();
  1786. mLongTapTimer = nullptr;
  1787. SynthesizeNativeTouchPoint(mLongTapTouchPoint->mPointerId, TOUCH_CANCEL,
  1788. mLongTapTouchPoint->mPosition, 0, 0, nullptr);
  1789. mLongTapTouchPoint = nullptr;
  1790. return NS_OK;
  1791. }
  1792. MultiTouchInput
  1793. nsBaseWidget::UpdateSynthesizedTouchState(MultiTouchInput* aState,
  1794. uint32_t aTime,
  1795. mozilla::TimeStamp aTimeStamp,
  1796. uint32_t aPointerId,
  1797. TouchPointerState aPointerState,
  1798. LayoutDeviceIntPoint aPoint,
  1799. double aPointerPressure,
  1800. uint32_t aPointerOrientation)
  1801. {
  1802. ScreenIntPoint pointerScreenPoint = ViewAs<ScreenPixel>(aPoint,
  1803. PixelCastJustification::LayoutDeviceIsScreenForBounds);
  1804. // We can't dispatch *aState directly because (a) dispatching
  1805. // it might inadvertently modify it and (b) in the case of touchend or
  1806. // touchcancel events aState will hold the touches that are
  1807. // still down whereas the input dispatched needs to hold the removed
  1808. // touch(es). We use |inputToDispatch| for this purpose.
  1809. MultiTouchInput inputToDispatch;
  1810. inputToDispatch.mInputType = MULTITOUCH_INPUT;
  1811. inputToDispatch.mTime = aTime;
  1812. inputToDispatch.mTimeStamp = aTimeStamp;
  1813. int32_t index = aState->IndexOfTouch((int32_t)aPointerId);
  1814. if (aPointerState == TOUCH_CONTACT) {
  1815. if (index >= 0) {
  1816. // found an existing touch point, update it
  1817. SingleTouchData& point = aState->mTouches[index];
  1818. point.mScreenPoint = pointerScreenPoint;
  1819. point.mRotationAngle = (float)aPointerOrientation;
  1820. point.mForce = (float)aPointerPressure;
  1821. inputToDispatch.mType = MultiTouchInput::MULTITOUCH_MOVE;
  1822. } else {
  1823. // new touch point, add it
  1824. aState->mTouches.AppendElement(SingleTouchData(
  1825. (int32_t)aPointerId,
  1826. pointerScreenPoint,
  1827. ScreenSize(0, 0),
  1828. (float)aPointerOrientation,
  1829. (float)aPointerPressure));
  1830. inputToDispatch.mType = MultiTouchInput::MULTITOUCH_START;
  1831. }
  1832. inputToDispatch.mTouches = aState->mTouches;
  1833. } else {
  1834. MOZ_ASSERT(aPointerState == TOUCH_REMOVE || aPointerState == TOUCH_CANCEL);
  1835. // a touch point is being lifted, so remove it from the stored list
  1836. if (index >= 0) {
  1837. aState->mTouches.RemoveElementAt(index);
  1838. }
  1839. inputToDispatch.mType = (aPointerState == TOUCH_REMOVE
  1840. ? MultiTouchInput::MULTITOUCH_END
  1841. : MultiTouchInput::MULTITOUCH_CANCEL);
  1842. inputToDispatch.mTouches.AppendElement(SingleTouchData(
  1843. (int32_t)aPointerId,
  1844. pointerScreenPoint,
  1845. ScreenSize(0, 0),
  1846. (float)aPointerOrientation,
  1847. (float)aPointerPressure));
  1848. }
  1849. return inputToDispatch;
  1850. }
  1851. void
  1852. nsBaseWidget::RegisterPluginWindowForRemoteUpdates()
  1853. {
  1854. #if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
  1855. NS_NOTREACHED("nsBaseWidget::RegisterPluginWindowForRemoteUpdates not implemented!");
  1856. return;
  1857. #else
  1858. MOZ_ASSERT(NS_IsMainThread());
  1859. void* id = GetNativeData(NS_NATIVE_PLUGIN_ID);
  1860. if (!id) {
  1861. NS_WARNING("This is not a valid native widget!");
  1862. return;
  1863. }
  1864. MOZ_ASSERT(sPluginWidgetList);
  1865. sPluginWidgetList->Put(id, this);
  1866. #endif
  1867. }
  1868. void
  1869. nsBaseWidget::UnregisterPluginWindowForRemoteUpdates()
  1870. {
  1871. #if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
  1872. NS_NOTREACHED("nsBaseWidget::UnregisterPluginWindowForRemoteUpdates not implemented!");
  1873. return;
  1874. #else
  1875. MOZ_ASSERT(NS_IsMainThread());
  1876. void* id = GetNativeData(NS_NATIVE_PLUGIN_ID);
  1877. if (!id) {
  1878. NS_WARNING("This is not a valid native widget!");
  1879. return;
  1880. }
  1881. MOZ_ASSERT(sPluginWidgetList);
  1882. sPluginWidgetList->Remove(id);
  1883. #endif
  1884. }
  1885. // static
  1886. nsIWidget*
  1887. nsIWidget::LookupRegisteredPluginWindow(uintptr_t aWindowID)
  1888. {
  1889. #if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
  1890. NS_NOTREACHED("nsBaseWidget::LookupRegisteredPluginWindow not implemented!");
  1891. return nullptr;
  1892. #else
  1893. MOZ_ASSERT(NS_IsMainThread());
  1894. MOZ_ASSERT(sPluginWidgetList);
  1895. return sPluginWidgetList->GetWeak((void*)aWindowID);
  1896. #endif
  1897. }
  1898. // static
  1899. void
  1900. nsIWidget::UpdateRegisteredPluginWindowVisibility(uintptr_t aOwnerWidget,
  1901. nsTArray<uintptr_t>& aPluginIds)
  1902. {
  1903. #if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
  1904. NS_NOTREACHED("nsBaseWidget::UpdateRegisteredPluginWindowVisibility not implemented!");
  1905. return;
  1906. #else
  1907. MOZ_ASSERT(NS_IsMainThread());
  1908. MOZ_ASSERT(sPluginWidgetList);
  1909. // Our visible list is associated with a compositor which is associated with
  1910. // a specific top level window. We use the parent widget during iteration
  1911. // to skip the plugin widgets owned by other top level windows.
  1912. for (auto iter = sPluginWidgetList->Iter(); !iter.Done(); iter.Next()) {
  1913. const void* windowId = iter.Key();
  1914. nsIWidget* widget = iter.UserData();
  1915. MOZ_ASSERT(windowId);
  1916. MOZ_ASSERT(widget);
  1917. if (!widget->Destroyed()) {
  1918. if ((uintptr_t)widget->GetParent() == aOwnerWidget) {
  1919. widget->Show(aPluginIds.Contains((uintptr_t)windowId));
  1920. }
  1921. }
  1922. }
  1923. #endif
  1924. }
  1925. #if defined(XP_WIN)
  1926. // static
  1927. void
  1928. nsIWidget::CaptureRegisteredPlugins(uintptr_t aOwnerWidget)
  1929. {
  1930. MOZ_ASSERT(NS_IsMainThread());
  1931. MOZ_ASSERT(sPluginWidgetList);
  1932. // Our visible list is associated with a compositor which is associated with
  1933. // a specific top level window. We use the parent widget during iteration
  1934. // to skip the plugin widgets owned by other top level windows.
  1935. for (auto iter = sPluginWidgetList->Iter(); !iter.Done(); iter.Next()) {
  1936. const void* windowId = iter.Key();
  1937. nsIWidget* widget = iter.UserData();
  1938. MOZ_ASSERT(windowId);
  1939. MOZ_ASSERT(widget);
  1940. if (!widget->Destroyed() && widget->IsVisible()) {
  1941. if ((uintptr_t)widget->GetParent() == aOwnerWidget) {
  1942. widget->UpdateScrollCapture();
  1943. }
  1944. }
  1945. }
  1946. }
  1947. uint64_t
  1948. nsBaseWidget::CreateScrollCaptureContainer()
  1949. {
  1950. mScrollCaptureContainer =
  1951. LayerManager::CreateImageContainer(ImageContainer::ASYNCHRONOUS);
  1952. if (!mScrollCaptureContainer) {
  1953. NS_WARNING("Failed to create ImageContainer for widget image capture.");
  1954. return ImageContainer::sInvalidAsyncContainerId;
  1955. }
  1956. return mScrollCaptureContainer->GetAsyncContainerID();
  1957. }
  1958. void
  1959. nsBaseWidget::UpdateScrollCapture()
  1960. {
  1961. // Don't capture if no container or no size.
  1962. if (!mScrollCaptureContainer || mBounds.width <= 0 || mBounds.height <= 0) {
  1963. return;
  1964. }
  1965. // If the derived class cannot take a snapshot, for example due to clipping,
  1966. // then it is responsible for creating a fallback. If null is returned, this
  1967. // means that we want to keep the existing snapshot.
  1968. RefPtr<gfx::SourceSurface> snapshot = CreateScrollSnapshot();
  1969. if (!snapshot) {
  1970. return;
  1971. }
  1972. ImageContainer::NonOwningImage holder(new SourceSurfaceImage(snapshot));
  1973. AutoTArray<ImageContainer::NonOwningImage, 1> imageList;
  1974. imageList.AppendElement(holder);
  1975. mScrollCaptureContainer->SetCurrentImages(imageList);
  1976. }
  1977. void
  1978. nsBaseWidget::DefaultFillScrollCapture(DrawTarget* aSnapshotDrawTarget)
  1979. {
  1980. gfx::IntSize dtSize = aSnapshotDrawTarget->GetSize();
  1981. aSnapshotDrawTarget->FillRect(
  1982. gfx::Rect(0, 0, dtSize.width, dtSize.height),
  1983. gfx::ColorPattern(gfx::Color::FromABGR(kScrollCaptureFillColor)),
  1984. gfx::DrawOptions(1.f, gfx::CompositionOp::OP_SOURCE));
  1985. aSnapshotDrawTarget->Flush();
  1986. }
  1987. #endif
  1988. NS_IMETHODIMP_(nsIWidget::NativeIMEContext)
  1989. nsIWidget::GetNativeIMEContext()
  1990. {
  1991. return NativeIMEContext(this);
  1992. }
  1993. nsresult
  1994. nsIWidget::OnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
  1995. nsIKeyEventInPluginCallback* aCallback)
  1996. {
  1997. return NS_ERROR_NOT_IMPLEMENTED;
  1998. }
  1999. namespace mozilla {
  2000. namespace widget {
  2001. const char*
  2002. ToChar(IMEMessage aIMEMessage)
  2003. {
  2004. switch (aIMEMessage) {
  2005. case NOTIFY_IME_OF_NOTHING:
  2006. return "NOTIFY_IME_OF_NOTHING";
  2007. case NOTIFY_IME_OF_FOCUS:
  2008. return "NOTIFY_IME_OF_FOCUS";
  2009. case NOTIFY_IME_OF_BLUR:
  2010. return "NOTIFY_IME_OF_BLUR";
  2011. case NOTIFY_IME_OF_SELECTION_CHANGE:
  2012. return "NOTIFY_IME_OF_SELECTION_CHANGE";
  2013. case NOTIFY_IME_OF_TEXT_CHANGE:
  2014. return "NOTIFY_IME_OF_TEXT_CHANGE";
  2015. case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED:
  2016. return "NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED";
  2017. case NOTIFY_IME_OF_POSITION_CHANGE:
  2018. return "NOTIFY_IME_OF_POSITION_CHANGE";
  2019. case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
  2020. return "NOTIFY_IME_OF_MOUSE_BUTTON_EVENT";
  2021. case REQUEST_TO_COMMIT_COMPOSITION:
  2022. return "REQUEST_TO_COMMIT_COMPOSITION";
  2023. case REQUEST_TO_CANCEL_COMPOSITION:
  2024. return "REQUEST_TO_CANCEL_COMPOSITION";
  2025. default:
  2026. return "Unexpected value";
  2027. }
  2028. }
  2029. void
  2030. NativeIMEContext::Init(nsIWidget* aWidget)
  2031. {
  2032. if (!aWidget) {
  2033. mRawNativeIMEContext = reinterpret_cast<uintptr_t>(nullptr);
  2034. mOriginProcessID = static_cast<uint64_t>(-1);
  2035. return;
  2036. }
  2037. if (!XRE_IsContentProcess()) {
  2038. mRawNativeIMEContext = reinterpret_cast<uintptr_t>(
  2039. aWidget->GetNativeData(NS_RAW_NATIVE_IME_CONTEXT));
  2040. mOriginProcessID = 0;
  2041. return;
  2042. }
  2043. // If this is created in a child process, aWidget is an instance of
  2044. // PuppetWidget which doesn't support NS_RAW_NATIVE_IME_CONTEXT.
  2045. // Instead of that PuppetWidget::GetNativeIMEContext() returns cached
  2046. // native IME context of the parent process.
  2047. *this = aWidget->GetNativeIMEContext();
  2048. }
  2049. void
  2050. NativeIMEContext::InitWithRawNativeIMEContext(void* aRawNativeIMEContext)
  2051. {
  2052. if (NS_WARN_IF(!aRawNativeIMEContext)) {
  2053. mRawNativeIMEContext = reinterpret_cast<uintptr_t>(nullptr);
  2054. mOriginProcessID = static_cast<uint64_t>(-1);
  2055. return;
  2056. }
  2057. mRawNativeIMEContext = reinterpret_cast<uintptr_t>(aRawNativeIMEContext);
  2058. mOriginProcessID =
  2059. XRE_IsContentProcess() ? ContentChild::GetSingleton()->GetID() : 0;
  2060. }
  2061. void
  2062. IMENotification::TextChangeDataBase::MergeWith(
  2063. const IMENotification::TextChangeDataBase& aOther)
  2064. {
  2065. MOZ_ASSERT(aOther.IsValid(),
  2066. "Merging data must store valid data");
  2067. MOZ_ASSERT(aOther.mStartOffset <= aOther.mRemovedEndOffset,
  2068. "end of removed text must be same or larger than start");
  2069. MOZ_ASSERT(aOther.mStartOffset <= aOther.mAddedEndOffset,
  2070. "end of added text must be same or larger than start");
  2071. if (!IsValid()) {
  2072. *this = aOther;
  2073. return;
  2074. }
  2075. // |mStartOffset| and |mRemovedEndOffset| represent all replaced or removed
  2076. // text ranges. I.e., mStartOffset should be the smallest offset of all
  2077. // modified text ranges in old text. |mRemovedEndOffset| should be the
  2078. // largest end offset in old text of all modified text ranges.
  2079. // |mAddedEndOffset| represents the end offset of all inserted text ranges.
  2080. // I.e., only this is an offset in new text.
  2081. // In other words, between mStartOffset and |mRemovedEndOffset| of the
  2082. // premodified text was already removed. And some text whose length is
  2083. // |mAddedEndOffset - mStartOffset| is inserted to |mStartOffset|. I.e.,
  2084. // this allows IME to mark dirty the modified text range with |mStartOffset|
  2085. // and |mRemovedEndOffset| if IME stores all text of the focused editor and
  2086. // to compute new text length with |mAddedEndOffset| and |mRemovedEndOffset|.
  2087. // Additionally, IME can retrieve only the text between |mStartOffset| and
  2088. // |mAddedEndOffset| for updating stored text.
  2089. // For comparing new and old |mStartOffset|/|mRemovedEndOffset| values, they
  2090. // should be adjusted to be in same text. The |newData.mStartOffset| and
  2091. // |newData.mRemovedEndOffset| should be computed as in old text because
  2092. // |mStartOffset| and |mRemovedEndOffset| represent the modified text range
  2093. // in the old text but even if some text before the values of the newData
  2094. // has already been modified, the values don't include the changes.
  2095. // For comparing new and old |mAddedEndOffset| values, they should be
  2096. // adjusted to be in same text. The |oldData.mAddedEndOffset| should be
  2097. // computed as in the new text because |mAddedEndOffset| indicates the end
  2098. // offset of inserted text in the new text but |oldData.mAddedEndOffset|
  2099. // doesn't include any changes of the text before |newData.mAddedEndOffset|.
  2100. const TextChangeDataBase& newData = aOther;
  2101. const TextChangeDataBase oldData = *this;
  2102. // mCausedOnlyByComposition should be true only when all changes are caused
  2103. // by composition.
  2104. mCausedOnlyByComposition =
  2105. newData.mCausedOnlyByComposition && oldData.mCausedOnlyByComposition;
  2106. // mIncludingChangesWithoutComposition should be true if at least one of
  2107. // merged changes occurred without composition.
  2108. mIncludingChangesWithoutComposition =
  2109. newData.mIncludingChangesWithoutComposition ||
  2110. oldData.mIncludingChangesWithoutComposition;
  2111. // mIncludingChangesDuringComposition should be true when at least one of
  2112. // the merged non-composition changes occurred during the latest composition.
  2113. if (!newData.mCausedOnlyByComposition &&
  2114. !newData.mIncludingChangesDuringComposition) {
  2115. MOZ_ASSERT(newData.mIncludingChangesWithoutComposition);
  2116. MOZ_ASSERT(mIncludingChangesWithoutComposition);
  2117. // If new change is neither caused by composition nor occurred during
  2118. // composition, set mIncludingChangesDuringComposition to false because
  2119. // IME doesn't want outdated text changes as text change during current
  2120. // composition.
  2121. mIncludingChangesDuringComposition = false;
  2122. } else {
  2123. // Otherwise, set mIncludingChangesDuringComposition to true if either
  2124. // oldData or newData includes changes during composition.
  2125. mIncludingChangesDuringComposition =
  2126. newData.mIncludingChangesDuringComposition ||
  2127. oldData.mIncludingChangesDuringComposition;
  2128. }
  2129. if (newData.mStartOffset >= oldData.mAddedEndOffset) {
  2130. // Case 1:
  2131. // If new start is after old end offset of added text, it means that text
  2132. // after the modified range is modified. Like:
  2133. // added range of old change: +----------+
  2134. // removed range of new change: +----------+
  2135. // So, the old start offset is always the smaller offset.
  2136. mStartOffset = oldData.mStartOffset;
  2137. // The new end offset of removed text is moved by the old change and we
  2138. // need to cancel the move of the old change for comparing the offsets in
  2139. // same text because it doesn't make sensce to compare offsets in different
  2140. // text.
  2141. uint32_t newRemovedEndOffsetInOldText =
  2142. newData.mRemovedEndOffset - oldData.Difference();
  2143. mRemovedEndOffset =
  2144. std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
  2145. // The new end offset of added text is always the larger offset.
  2146. mAddedEndOffset = newData.mAddedEndOffset;
  2147. return;
  2148. }
  2149. if (newData.mStartOffset >= oldData.mStartOffset) {
  2150. // If new start is in the modified range, it means that new data changes
  2151. // a part or all of the range.
  2152. mStartOffset = oldData.mStartOffset;
  2153. if (newData.mRemovedEndOffset >= oldData.mAddedEndOffset) {
  2154. // Case 2:
  2155. // If new end of removed text is greater than old end of added text, it
  2156. // means that all or a part of modified range modified again and text
  2157. // after the modified range is also modified. Like:
  2158. // added range of old change: +----------+
  2159. // removed range of new change: +----------+
  2160. // So, the new removed end offset is moved by the old change and we need
  2161. // to cancel the move of the old change for comparing the offsets in the
  2162. // same text because it doesn't make sense to compare the offsets in
  2163. // different text.
  2164. uint32_t newRemovedEndOffsetInOldText =
  2165. newData.mRemovedEndOffset - oldData.Difference();
  2166. mRemovedEndOffset =
  2167. std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
  2168. // The old end of added text is replaced by new change. So, it should be
  2169. // same as the new start. On the other hand, the new added end offset is
  2170. // always same or larger. Therefore, the merged end offset of added
  2171. // text should be the new end offset of added text.
  2172. mAddedEndOffset = newData.mAddedEndOffset;
  2173. return;
  2174. }
  2175. // Case 3:
  2176. // If new end of removed text is less than old end of added text, it means
  2177. // that only a part of the modified range is modified again. Like:
  2178. // added range of old change: +------------+
  2179. // removed range of new change: +-----+
  2180. // So, the new end offset of removed text should be same as the old end
  2181. // offset of removed text. Therefore, the merged end offset of removed
  2182. // text should be the old text change's |mRemovedEndOffset|.
  2183. mRemovedEndOffset = oldData.mRemovedEndOffset;
  2184. // The old end of added text is moved by new change. So, we need to cancel
  2185. // the move of the new change for comparing the offsets in same text.
  2186. uint32_t oldAddedEndOffsetInNewText =
  2187. oldData.mAddedEndOffset + newData.Difference();
  2188. mAddedEndOffset =
  2189. std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
  2190. return;
  2191. }
  2192. if (newData.mRemovedEndOffset >= oldData.mStartOffset) {
  2193. // If new end of removed text is greater than old start (and new start is
  2194. // less than old start), it means that a part of modified range is modified
  2195. // again and some new text before the modified range is also modified.
  2196. MOZ_ASSERT(newData.mStartOffset < oldData.mStartOffset,
  2197. "new start offset should be less than old one here");
  2198. mStartOffset = newData.mStartOffset;
  2199. if (newData.mRemovedEndOffset >= oldData.mAddedEndOffset) {
  2200. // Case 4:
  2201. // If new end of removed text is greater than old end of added text, it
  2202. // means that all modified text and text after the modified range is
  2203. // modified. Like:
  2204. // added range of old change: +----------+
  2205. // removed range of new change: +------------------+
  2206. // So, the new end of removed text is moved by the old change. Therefore,
  2207. // we need to cancel the move of the old change for comparing the offsets
  2208. // in same text because it doesn't make sense to compare the offsets in
  2209. // different text.
  2210. uint32_t newRemovedEndOffsetInOldText =
  2211. newData.mRemovedEndOffset - oldData.Difference();
  2212. mRemovedEndOffset =
  2213. std::max(newRemovedEndOffsetInOldText, oldData.mRemovedEndOffset);
  2214. // The old end of added text is replaced by new change. So, the old end
  2215. // offset of added text is same as new text change's start offset. Then,
  2216. // new change's end offset of added text is always same or larger than
  2217. // it. Therefore, merged end offset of added text is always the new end
  2218. // offset of added text.
  2219. mAddedEndOffset = newData.mAddedEndOffset;
  2220. return;
  2221. }
  2222. // Case 5:
  2223. // If new end of removed text is less than old end of added text, it
  2224. // means that only a part of the modified range is modified again. Like:
  2225. // added range of old change: +----------+
  2226. // removed range of new change: +----------+
  2227. // So, the new end of removed text should be same as old end of removed
  2228. // text for preventing end of removed text to be modified. Therefore,
  2229. // merged end offset of removed text is always the old end offset of removed
  2230. // text.
  2231. mRemovedEndOffset = oldData.mRemovedEndOffset;
  2232. // The old end of added text is moved by this change. So, we need to
  2233. // cancel the move of the new change for comparing the offsets in same text
  2234. // because it doesn't make sense to compare the offsets in different text.
  2235. uint32_t oldAddedEndOffsetInNewText =
  2236. oldData.mAddedEndOffset + newData.Difference();
  2237. mAddedEndOffset =
  2238. std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
  2239. return;
  2240. }
  2241. // Case 6:
  2242. // Otherwise, i.e., both new end of added text and new start are less than
  2243. // old start, text before the modified range is modified. Like:
  2244. // added range of old change: +----------+
  2245. // removed range of new change: +----------+
  2246. MOZ_ASSERT(newData.mStartOffset < oldData.mStartOffset,
  2247. "new start offset should be less than old one here");
  2248. mStartOffset = newData.mStartOffset;
  2249. MOZ_ASSERT(newData.mRemovedEndOffset < oldData.mRemovedEndOffset,
  2250. "new removed end offset should be less than old one here");
  2251. mRemovedEndOffset = oldData.mRemovedEndOffset;
  2252. // The end of added text should be adjusted with the new difference.
  2253. uint32_t oldAddedEndOffsetInNewText =
  2254. oldData.mAddedEndOffset + newData.Difference();
  2255. mAddedEndOffset =
  2256. std::max(newData.mAddedEndOffset, oldAddedEndOffsetInNewText);
  2257. }
  2258. #ifdef DEBUG
  2259. // Let's test the code of merging multiple text change data in debug build
  2260. // and crash if one of them fails because this feature is very complex but
  2261. // cannot be tested with mochitest.
  2262. void
  2263. IMENotification::TextChangeDataBase::Test()
  2264. {
  2265. static bool gTestTextChangeEvent = true;
  2266. if (!gTestTextChangeEvent) {
  2267. return;
  2268. }
  2269. gTestTextChangeEvent = false;
  2270. /****************************************************************************
  2271. * Case 1
  2272. ****************************************************************************/
  2273. // Appending text
  2274. MergeWith(TextChangeData(10, 10, 20, false, false));
  2275. MergeWith(TextChangeData(20, 20, 35, false, false));
  2276. MOZ_ASSERT(mStartOffset == 10,
  2277. "Test 1-1-1: mStartOffset should be the first offset");
  2278. MOZ_ASSERT(mRemovedEndOffset == 10, // 20 - (20 - 10)
  2279. "Test 1-1-2: mRemovedEndOffset should be the first end of removed text");
  2280. MOZ_ASSERT(mAddedEndOffset == 35,
  2281. "Test 1-1-3: mAddedEndOffset should be the last end of added text");
  2282. Clear();
  2283. // Removing text (longer line -> shorter line)
  2284. MergeWith(TextChangeData(10, 20, 10, false, false));
  2285. MergeWith(TextChangeData(10, 30, 10, false, false));
  2286. MOZ_ASSERT(mStartOffset == 10,
  2287. "Test 1-2-1: mStartOffset should be the first offset");
  2288. MOZ_ASSERT(mRemovedEndOffset == 40, // 30 + (10 - 20)
  2289. "Test 1-2-2: mRemovedEndOffset should be the the last end of removed text "
  2290. "with already removed length");
  2291. MOZ_ASSERT(mAddedEndOffset == 10,
  2292. "Test 1-2-3: mAddedEndOffset should be the last end of added text");
  2293. Clear();
  2294. // Removing text (shorter line -> longer line)
  2295. MergeWith(TextChangeData(10, 20, 10, false, false));
  2296. MergeWith(TextChangeData(10, 15, 10, false, false));
  2297. MOZ_ASSERT(mStartOffset == 10,
  2298. "Test 1-3-1: mStartOffset should be the first offset");
  2299. MOZ_ASSERT(mRemovedEndOffset == 25, // 15 + (10 - 20)
  2300. "Test 1-3-2: mRemovedEndOffset should be the the last end of removed text "
  2301. "with already removed length");
  2302. MOZ_ASSERT(mAddedEndOffset == 10,
  2303. "Test 1-3-3: mAddedEndOffset should be the last end of added text");
  2304. Clear();
  2305. // Appending text at different point (not sure if actually occurs)
  2306. MergeWith(TextChangeData(10, 10, 20, false, false));
  2307. MergeWith(TextChangeData(55, 55, 60, false, false));
  2308. MOZ_ASSERT(mStartOffset == 10,
  2309. "Test 1-4-1: mStartOffset should be the smallest offset");
  2310. MOZ_ASSERT(mRemovedEndOffset == 45, // 55 - (10 - 20)
  2311. "Test 1-4-2: mRemovedEndOffset should be the the largest end of removed "
  2312. "text without already added length");
  2313. MOZ_ASSERT(mAddedEndOffset == 60,
  2314. "Test 1-4-3: mAddedEndOffset should be the last end of added text");
  2315. Clear();
  2316. // Removing text at different point (not sure if actually occurs)
  2317. MergeWith(TextChangeData(10, 20, 10, false, false));
  2318. MergeWith(TextChangeData(55, 68, 55, false, false));
  2319. MOZ_ASSERT(mStartOffset == 10,
  2320. "Test 1-5-1: mStartOffset should be the smallest offset");
  2321. MOZ_ASSERT(mRemovedEndOffset == 78, // 68 - (10 - 20)
  2322. "Test 1-5-2: mRemovedEndOffset should be the the largest end of removed "
  2323. "text with already removed length");
  2324. MOZ_ASSERT(mAddedEndOffset == 55,
  2325. "Test 1-5-3: mAddedEndOffset should be the largest end of added text");
  2326. Clear();
  2327. // Replacing text and append text (becomes longer)
  2328. MergeWith(TextChangeData(30, 35, 32, false, false));
  2329. MergeWith(TextChangeData(32, 32, 40, false, false));
  2330. MOZ_ASSERT(mStartOffset == 30,
  2331. "Test 1-6-1: mStartOffset should be the smallest offset");
  2332. MOZ_ASSERT(mRemovedEndOffset == 35, // 32 - (32 - 35)
  2333. "Test 1-6-2: mRemovedEndOffset should be the the first end of removed "
  2334. "text");
  2335. MOZ_ASSERT(mAddedEndOffset == 40,
  2336. "Test 1-6-3: mAddedEndOffset should be the last end of added text");
  2337. Clear();
  2338. // Replacing text and append text (becomes shorter)
  2339. MergeWith(TextChangeData(30, 35, 32, false, false));
  2340. MergeWith(TextChangeData(32, 32, 33, false, false));
  2341. MOZ_ASSERT(mStartOffset == 30,
  2342. "Test 1-7-1: mStartOffset should be the smallest offset");
  2343. MOZ_ASSERT(mRemovedEndOffset == 35, // 32 - (32 - 35)
  2344. "Test 1-7-2: mRemovedEndOffset should be the the first end of removed "
  2345. "text");
  2346. MOZ_ASSERT(mAddedEndOffset == 33,
  2347. "Test 1-7-3: mAddedEndOffset should be the last end of added text");
  2348. Clear();
  2349. // Removing text and replacing text after first range (not sure if actually
  2350. // occurs)
  2351. MergeWith(TextChangeData(30, 35, 30, false, false));
  2352. MergeWith(TextChangeData(32, 34, 48, false, false));
  2353. MOZ_ASSERT(mStartOffset == 30,
  2354. "Test 1-8-1: mStartOffset should be the smallest offset");
  2355. MOZ_ASSERT(mRemovedEndOffset == 39, // 34 - (30 - 35)
  2356. "Test 1-8-2: mRemovedEndOffset should be the the first end of removed text "
  2357. "without already removed text");
  2358. MOZ_ASSERT(mAddedEndOffset == 48,
  2359. "Test 1-8-3: mAddedEndOffset should be the last end of added text");
  2360. Clear();
  2361. // Removing text and replacing text after first range (not sure if actually
  2362. // occurs)
  2363. MergeWith(TextChangeData(30, 35, 30, false, false));
  2364. MergeWith(TextChangeData(32, 38, 36, false, false));
  2365. MOZ_ASSERT(mStartOffset == 30,
  2366. "Test 1-9-1: mStartOffset should be the smallest offset");
  2367. MOZ_ASSERT(mRemovedEndOffset == 43, // 38 - (30 - 35)
  2368. "Test 1-9-2: mRemovedEndOffset should be the the first end of removed text "
  2369. "without already removed text");
  2370. MOZ_ASSERT(mAddedEndOffset == 36,
  2371. "Test 1-9-3: mAddedEndOffset should be the last end of added text");
  2372. Clear();
  2373. /****************************************************************************
  2374. * Case 2
  2375. ****************************************************************************/
  2376. // Replacing text in around end of added text (becomes shorter) (not sure
  2377. // if actually occurs)
  2378. MergeWith(TextChangeData(50, 50, 55, false, false));
  2379. MergeWith(TextChangeData(53, 60, 54, false, false));
  2380. MOZ_ASSERT(mStartOffset == 50,
  2381. "Test 2-1-1: mStartOffset should be the smallest offset");
  2382. MOZ_ASSERT(mRemovedEndOffset == 55, // 60 - (55 - 50)
  2383. "Test 2-1-2: mRemovedEndOffset should be the the last end of removed text "
  2384. "without already added text length");
  2385. MOZ_ASSERT(mAddedEndOffset == 54,
  2386. "Test 2-1-3: mAddedEndOffset should be the last end of added text");
  2387. Clear();
  2388. // Replacing text around end of added text (becomes longer) (not sure
  2389. // if actually occurs)
  2390. MergeWith(TextChangeData(50, 50, 55, false, false));
  2391. MergeWith(TextChangeData(54, 62, 68, false, false));
  2392. MOZ_ASSERT(mStartOffset == 50,
  2393. "Test 2-2-1: mStartOffset should be the smallest offset");
  2394. MOZ_ASSERT(mRemovedEndOffset == 57, // 62 - (55 - 50)
  2395. "Test 2-2-2: mRemovedEndOffset should be the the last end of removed text "
  2396. "without already added text length");
  2397. MOZ_ASSERT(mAddedEndOffset == 68,
  2398. "Test 2-2-3: mAddedEndOffset should be the last end of added text");
  2399. Clear();
  2400. // Replacing text around end of replaced text (became shorter) (not sure if
  2401. // actually occurs)
  2402. MergeWith(TextChangeData(36, 48, 45, false, false));
  2403. MergeWith(TextChangeData(43, 50, 49, false, false));
  2404. MOZ_ASSERT(mStartOffset == 36,
  2405. "Test 2-3-1: mStartOffset should be the smallest offset");
  2406. MOZ_ASSERT(mRemovedEndOffset == 53, // 50 - (45 - 48)
  2407. "Test 2-3-2: mRemovedEndOffset should be the the last end of removed text "
  2408. "without already removed text length");
  2409. MOZ_ASSERT(mAddedEndOffset == 49,
  2410. "Test 2-3-3: mAddedEndOffset should be the last end of added text");
  2411. Clear();
  2412. // Replacing text around end of replaced text (became longer) (not sure if
  2413. // actually occurs)
  2414. MergeWith(TextChangeData(36, 52, 53, false, false));
  2415. MergeWith(TextChangeData(43, 68, 61, false, false));
  2416. MOZ_ASSERT(mStartOffset == 36,
  2417. "Test 2-4-1: mStartOffset should be the smallest offset");
  2418. MOZ_ASSERT(mRemovedEndOffset == 67, // 68 - (53 - 52)
  2419. "Test 2-4-2: mRemovedEndOffset should be the the last end of removed text "
  2420. "without already added text length");
  2421. MOZ_ASSERT(mAddedEndOffset == 61,
  2422. "Test 2-4-3: mAddedEndOffset should be the last end of added text");
  2423. Clear();
  2424. /****************************************************************************
  2425. * Case 3
  2426. ****************************************************************************/
  2427. // Appending text in already added text (not sure if actually occurs)
  2428. MergeWith(TextChangeData(10, 10, 20, false, false));
  2429. MergeWith(TextChangeData(15, 15, 30, false, false));
  2430. MOZ_ASSERT(mStartOffset == 10,
  2431. "Test 3-1-1: mStartOffset should be the smallest offset");
  2432. MOZ_ASSERT(mRemovedEndOffset == 10,
  2433. "Test 3-1-2: mRemovedEndOffset should be the the first end of removed text");
  2434. MOZ_ASSERT(mAddedEndOffset == 35, // 20 + (30 - 15)
  2435. "Test 3-1-3: mAddedEndOffset should be the first end of added text with "
  2436. "added text length by the new change");
  2437. Clear();
  2438. // Replacing text in added text (not sure if actually occurs)
  2439. MergeWith(TextChangeData(50, 50, 55, false, false));
  2440. MergeWith(TextChangeData(52, 53, 56, false, false));
  2441. MOZ_ASSERT(mStartOffset == 50,
  2442. "Test 3-2-1: mStartOffset should be the smallest offset");
  2443. MOZ_ASSERT(mRemovedEndOffset == 50,
  2444. "Test 3-2-2: mRemovedEndOffset should be the the first end of removed text");
  2445. MOZ_ASSERT(mAddedEndOffset == 58, // 55 + (56 - 53)
  2446. "Test 3-2-3: mAddedEndOffset should be the first end of added text with "
  2447. "added text length by the new change");
  2448. Clear();
  2449. // Replacing text in replaced text (became shorter) (not sure if actually
  2450. // occurs)
  2451. MergeWith(TextChangeData(36, 48, 45, false, false));
  2452. MergeWith(TextChangeData(37, 38, 50, false, false));
  2453. MOZ_ASSERT(mStartOffset == 36,
  2454. "Test 3-3-1: mStartOffset should be the smallest offset");
  2455. MOZ_ASSERT(mRemovedEndOffset == 48,
  2456. "Test 3-3-2: mRemovedEndOffset should be the the first end of removed text");
  2457. MOZ_ASSERT(mAddedEndOffset == 57, // 45 + (50 - 38)
  2458. "Test 3-3-3: mAddedEndOffset should be the first end of added text with "
  2459. "added text length by the new change");
  2460. Clear();
  2461. // Replacing text in replaced text (became longer) (not sure if actually
  2462. // occurs)
  2463. MergeWith(TextChangeData(32, 48, 53, false, false));
  2464. MergeWith(TextChangeData(43, 50, 52, false, false));
  2465. MOZ_ASSERT(mStartOffset == 32,
  2466. "Test 3-4-1: mStartOffset should be the smallest offset");
  2467. MOZ_ASSERT(mRemovedEndOffset == 48,
  2468. "Test 3-4-2: mRemovedEndOffset should be the the last end of removed text "
  2469. "without already added text length");
  2470. MOZ_ASSERT(mAddedEndOffset == 55, // 53 + (52 - 50)
  2471. "Test 3-4-3: mAddedEndOffset should be the first end of added text with "
  2472. "added text length by the new change");
  2473. Clear();
  2474. // Replacing text in replaced text (became shorter) (not sure if actually
  2475. // occurs)
  2476. MergeWith(TextChangeData(36, 48, 50, false, false));
  2477. MergeWith(TextChangeData(37, 49, 47, false, false));
  2478. MOZ_ASSERT(mStartOffset == 36,
  2479. "Test 3-5-1: mStartOffset should be the smallest offset");
  2480. MOZ_ASSERT(mRemovedEndOffset == 48,
  2481. "Test 3-5-2: mRemovedEndOffset should be the the first end of removed "
  2482. "text");
  2483. MOZ_ASSERT(mAddedEndOffset == 48, // 50 + (47 - 49)
  2484. "Test 3-5-3: mAddedEndOffset should be the first end of added text without "
  2485. "removed text length by the new change");
  2486. Clear();
  2487. // Replacing text in replaced text (became longer) (not sure if actually
  2488. // occurs)
  2489. MergeWith(TextChangeData(32, 48, 53, false, false));
  2490. MergeWith(TextChangeData(43, 50, 47, false, false));
  2491. MOZ_ASSERT(mStartOffset == 32,
  2492. "Test 3-6-1: mStartOffset should be the smallest offset");
  2493. MOZ_ASSERT(mRemovedEndOffset == 48,
  2494. "Test 3-6-2: mRemovedEndOffset should be the the last end of removed text "
  2495. "without already added text length");
  2496. MOZ_ASSERT(mAddedEndOffset == 50, // 53 + (47 - 50)
  2497. "Test 3-6-3: mAddedEndOffset should be the first end of added text without "
  2498. "removed text length by the new change");
  2499. Clear();
  2500. /****************************************************************************
  2501. * Case 4
  2502. ****************************************************************************/
  2503. // Replacing text all of already append text (not sure if actually occurs)
  2504. MergeWith(TextChangeData(50, 50, 55, false, false));
  2505. MergeWith(TextChangeData(44, 66, 68, false, false));
  2506. MOZ_ASSERT(mStartOffset == 44,
  2507. "Test 4-1-1: mStartOffset should be the smallest offset");
  2508. MOZ_ASSERT(mRemovedEndOffset == 61, // 66 - (55 - 50)
  2509. "Test 4-1-2: mRemovedEndOffset should be the the last end of removed text "
  2510. "without already added text length");
  2511. MOZ_ASSERT(mAddedEndOffset == 68,
  2512. "Test 4-1-3: mAddedEndOffset should be the last end of added text");
  2513. Clear();
  2514. // Replacing text around a point in which text was removed (not sure if
  2515. // actually occurs)
  2516. MergeWith(TextChangeData(50, 62, 50, false, false));
  2517. MergeWith(TextChangeData(44, 66, 68, false, false));
  2518. MOZ_ASSERT(mStartOffset == 44,
  2519. "Test 4-2-1: mStartOffset should be the smallest offset");
  2520. MOZ_ASSERT(mRemovedEndOffset == 78, // 66 - (50 - 62)
  2521. "Test 4-2-2: mRemovedEndOffset should be the the last end of removed text "
  2522. "without already removed text length");
  2523. MOZ_ASSERT(mAddedEndOffset == 68,
  2524. "Test 4-2-3: mAddedEndOffset should be the last end of added text");
  2525. Clear();
  2526. // Replacing text all replaced text (became shorter) (not sure if actually
  2527. // occurs)
  2528. MergeWith(TextChangeData(50, 62, 60, false, false));
  2529. MergeWith(TextChangeData(49, 128, 130, false, false));
  2530. MOZ_ASSERT(mStartOffset == 49,
  2531. "Test 4-3-1: mStartOffset should be the smallest offset");
  2532. MOZ_ASSERT(mRemovedEndOffset == 130, // 128 - (60 - 62)
  2533. "Test 4-3-2: mRemovedEndOffset should be the the last end of removed text "
  2534. "without already removed text length");
  2535. MOZ_ASSERT(mAddedEndOffset == 130,
  2536. "Test 4-3-3: mAddedEndOffset should be the last end of added text");
  2537. Clear();
  2538. // Replacing text all replaced text (became longer) (not sure if actually
  2539. // occurs)
  2540. MergeWith(TextChangeData(50, 61, 73, false, false));
  2541. MergeWith(TextChangeData(44, 100, 50, false, false));
  2542. MOZ_ASSERT(mStartOffset == 44,
  2543. "Test 4-4-1: mStartOffset should be the smallest offset");
  2544. MOZ_ASSERT(mRemovedEndOffset == 88, // 100 - (73 - 61)
  2545. "Test 4-4-2: mRemovedEndOffset should be the the last end of removed text "
  2546. "with already added text length");
  2547. MOZ_ASSERT(mAddedEndOffset == 50,
  2548. "Test 4-4-3: mAddedEndOffset should be the last end of added text");
  2549. Clear();
  2550. /****************************************************************************
  2551. * Case 5
  2552. ****************************************************************************/
  2553. // Replacing text around start of added text (not sure if actually occurs)
  2554. MergeWith(TextChangeData(50, 50, 55, false, false));
  2555. MergeWith(TextChangeData(48, 52, 49, false, false));
  2556. MOZ_ASSERT(mStartOffset == 48,
  2557. "Test 5-1-1: mStartOffset should be the smallest offset");
  2558. MOZ_ASSERT(mRemovedEndOffset == 50,
  2559. "Test 5-1-2: mRemovedEndOffset should be the the first end of removed "
  2560. "text");
  2561. MOZ_ASSERT(mAddedEndOffset == 52, // 55 + (52 - 49)
  2562. "Test 5-1-3: mAddedEndOffset should be the first end of added text with "
  2563. "added text length by the new change");
  2564. Clear();
  2565. // Replacing text around start of replaced text (became shorter) (not sure if
  2566. // actually occurs)
  2567. MergeWith(TextChangeData(50, 60, 58, false, false));
  2568. MergeWith(TextChangeData(43, 50, 48, false, false));
  2569. MOZ_ASSERT(mStartOffset == 43,
  2570. "Test 5-2-1: mStartOffset should be the smallest offset");
  2571. MOZ_ASSERT(mRemovedEndOffset == 60,
  2572. "Test 5-2-2: mRemovedEndOffset should be the the first end of removed "
  2573. "text");
  2574. MOZ_ASSERT(mAddedEndOffset == 56, // 58 + (48 - 50)
  2575. "Test 5-2-3: mAddedEndOffset should be the first end of added text without "
  2576. "removed text length by the new change");
  2577. Clear();
  2578. // Replacing text around start of replaced text (became longer) (not sure if
  2579. // actually occurs)
  2580. MergeWith(TextChangeData(50, 60, 68, false, false));
  2581. MergeWith(TextChangeData(43, 55, 53, false, false));
  2582. MOZ_ASSERT(mStartOffset == 43,
  2583. "Test 5-3-1: mStartOffset should be the smallest offset");
  2584. MOZ_ASSERT(mRemovedEndOffset == 60,
  2585. "Test 5-3-2: mRemovedEndOffset should be the the first end of removed "
  2586. "text");
  2587. MOZ_ASSERT(mAddedEndOffset == 66, // 68 + (53 - 55)
  2588. "Test 5-3-3: mAddedEndOffset should be the first end of added text without "
  2589. "removed text length by the new change");
  2590. Clear();
  2591. // Replacing text around start of replaced text (became shorter) (not sure if
  2592. // actually occurs)
  2593. MergeWith(TextChangeData(50, 60, 58, false, false));
  2594. MergeWith(TextChangeData(43, 50, 128, false, false));
  2595. MOZ_ASSERT(mStartOffset == 43,
  2596. "Test 5-4-1: mStartOffset should be the smallest offset");
  2597. MOZ_ASSERT(mRemovedEndOffset == 60,
  2598. "Test 5-4-2: mRemovedEndOffset should be the the first end of removed "
  2599. "text");
  2600. MOZ_ASSERT(mAddedEndOffset == 136, // 58 + (128 - 50)
  2601. "Test 5-4-3: mAddedEndOffset should be the first end of added text with "
  2602. "added text length by the new change");
  2603. Clear();
  2604. // Replacing text around start of replaced text (became longer) (not sure if
  2605. // actually occurs)
  2606. MergeWith(TextChangeData(50, 60, 68, false, false));
  2607. MergeWith(TextChangeData(43, 55, 65, false, false));
  2608. MOZ_ASSERT(mStartOffset == 43,
  2609. "Test 5-5-1: mStartOffset should be the smallest offset");
  2610. MOZ_ASSERT(mRemovedEndOffset == 60,
  2611. "Test 5-5-2: mRemovedEndOffset should be the the first end of removed "
  2612. "text");
  2613. MOZ_ASSERT(mAddedEndOffset == 78, // 68 + (65 - 55)
  2614. "Test 5-5-3: mAddedEndOffset should be the first end of added text with "
  2615. "added text length by the new change");
  2616. Clear();
  2617. /****************************************************************************
  2618. * Case 6
  2619. ****************************************************************************/
  2620. // Appending text before already added text (not sure if actually occurs)
  2621. MergeWith(TextChangeData(30, 30, 45, false, false));
  2622. MergeWith(TextChangeData(10, 10, 20, false, false));
  2623. MOZ_ASSERT(mStartOffset == 10,
  2624. "Test 6-1-1: mStartOffset should be the smallest offset");
  2625. MOZ_ASSERT(mRemovedEndOffset == 30,
  2626. "Test 6-1-2: mRemovedEndOffset should be the the largest end of removed "
  2627. "text");
  2628. MOZ_ASSERT(mAddedEndOffset == 55, // 45 + (20 - 10)
  2629. "Test 6-1-3: mAddedEndOffset should be the first end of added text with "
  2630. "added text length by the new change");
  2631. Clear();
  2632. // Removing text before already removed text (not sure if actually occurs)
  2633. MergeWith(TextChangeData(30, 35, 30, false, false));
  2634. MergeWith(TextChangeData(10, 25, 10, false, false));
  2635. MOZ_ASSERT(mStartOffset == 10,
  2636. "Test 6-2-1: mStartOffset should be the smallest offset");
  2637. MOZ_ASSERT(mRemovedEndOffset == 35,
  2638. "Test 6-2-2: mRemovedEndOffset should be the the largest end of removed "
  2639. "text");
  2640. MOZ_ASSERT(mAddedEndOffset == 15, // 30 - (25 - 10)
  2641. "Test 6-2-3: mAddedEndOffset should be the first end of added text with "
  2642. "removed text length by the new change");
  2643. Clear();
  2644. // Replacing text before already replaced text (not sure if actually occurs)
  2645. MergeWith(TextChangeData(50, 65, 70, false, false));
  2646. MergeWith(TextChangeData(13, 24, 15, false, false));
  2647. MOZ_ASSERT(mStartOffset == 13,
  2648. "Test 6-3-1: mStartOffset should be the smallest offset");
  2649. MOZ_ASSERT(mRemovedEndOffset == 65,
  2650. "Test 6-3-2: mRemovedEndOffset should be the the largest end of removed "
  2651. "text");
  2652. MOZ_ASSERT(mAddedEndOffset == 61, // 70 + (15 - 24)
  2653. "Test 6-3-3: mAddedEndOffset should be the first end of added text without "
  2654. "removed text length by the new change");
  2655. Clear();
  2656. // Replacing text before already replaced text (not sure if actually occurs)
  2657. MergeWith(TextChangeData(50, 65, 70, false, false));
  2658. MergeWith(TextChangeData(13, 24, 36, false, false));
  2659. MOZ_ASSERT(mStartOffset == 13,
  2660. "Test 6-4-1: mStartOffset should be the smallest offset");
  2661. MOZ_ASSERT(mRemovedEndOffset == 65,
  2662. "Test 6-4-2: mRemovedEndOffset should be the the largest end of removed "
  2663. "text");
  2664. MOZ_ASSERT(mAddedEndOffset == 82, // 70 + (36 - 24)
  2665. "Test 6-4-3: mAddedEndOffset should be the first end of added text without "
  2666. "removed text length by the new change");
  2667. Clear();
  2668. }
  2669. #endif // #ifdef DEBUG
  2670. } // namespace widget
  2671. } // namespace mozilla
  2672. #ifdef DEBUG
  2673. //////////////////////////////////////////////////////////////
  2674. //
  2675. // Convert a GUI event message code to a string.
  2676. // Makes it a lot easier to debug events.
  2677. //
  2678. // See gtk/nsWidget.cpp and windows/nsWindow.cpp
  2679. // for a DebugPrintEvent() function that uses
  2680. // this.
  2681. //
  2682. //////////////////////////////////////////////////////////////
  2683. /* static */ nsAutoString
  2684. nsBaseWidget::debug_GuiEventToString(WidgetGUIEvent* aGuiEvent)
  2685. {
  2686. NS_ASSERTION(nullptr != aGuiEvent,"cmon, null gui event.");
  2687. nsAutoString eventName(NS_LITERAL_STRING("UNKNOWN"));
  2688. #define _ASSIGN_eventName(_value,_name)\
  2689. case _value: eventName.AssignLiteral(_name) ; break
  2690. switch(aGuiEvent->mMessage)
  2691. {
  2692. _ASSIGN_eventName(eBlur,"eBlur");
  2693. _ASSIGN_eventName(eDrop,"eDrop");
  2694. _ASSIGN_eventName(eDragEnter,"eDragEnter");
  2695. _ASSIGN_eventName(eDragExit,"eDragExit");
  2696. _ASSIGN_eventName(eDragOver,"eDragOver");
  2697. _ASSIGN_eventName(eEditorInput,"eEditorInput");
  2698. _ASSIGN_eventName(eFocus,"eFocus");
  2699. _ASSIGN_eventName(eFocusIn,"eFocusIn");
  2700. _ASSIGN_eventName(eFocusOut,"eFocusOut");
  2701. _ASSIGN_eventName(eFormSelect,"eFormSelect");
  2702. _ASSIGN_eventName(eFormChange,"eFormChange");
  2703. _ASSIGN_eventName(eFormReset,"eFormReset");
  2704. _ASSIGN_eventName(eFormSubmit,"eFormSubmit");
  2705. _ASSIGN_eventName(eImageAbort,"eImageAbort");
  2706. _ASSIGN_eventName(eLoadError,"eLoadError");
  2707. _ASSIGN_eventName(eKeyDown,"eKeyDown");
  2708. _ASSIGN_eventName(eKeyPress,"eKeyPress");
  2709. _ASSIGN_eventName(eKeyUp,"eKeyUp");
  2710. _ASSIGN_eventName(eMouseEnterIntoWidget,"eMouseEnterIntoWidget");
  2711. _ASSIGN_eventName(eMouseExitFromWidget,"eMouseExitFromWidget");
  2712. _ASSIGN_eventName(eMouseDown,"eMouseDown");
  2713. _ASSIGN_eventName(eMouseUp,"eMouseUp");
  2714. _ASSIGN_eventName(eMouseClick,"eMouseClick");
  2715. _ASSIGN_eventName(eMouseAuxClick,"eMouseAuxClick");
  2716. _ASSIGN_eventName(eMouseDoubleClick,"eMouseDoubleClick");
  2717. _ASSIGN_eventName(eMouseMove,"eMouseMove");
  2718. _ASSIGN_eventName(eLoad,"eLoad");
  2719. _ASSIGN_eventName(ePopState,"ePopState");
  2720. _ASSIGN_eventName(eBeforeScriptExecute,"eBeforeScriptExecute");
  2721. _ASSIGN_eventName(eAfterScriptExecute,"eAfterScriptExecute");
  2722. _ASSIGN_eventName(eUnload,"eUnload");
  2723. _ASSIGN_eventName(eHashChange,"eHashChange");
  2724. _ASSIGN_eventName(eReadyStateChange,"eReadyStateChange");
  2725. _ASSIGN_eventName(eXULBroadcast, "eXULBroadcast");
  2726. _ASSIGN_eventName(eXULCommandUpdate, "eXULCommandUpdate");
  2727. #undef _ASSIGN_eventName
  2728. default:
  2729. {
  2730. char buf[32];
  2731. SprintfLiteral(buf,"UNKNOWN: %d",aGuiEvent->mMessage);
  2732. CopyASCIItoUTF16(buf, eventName);
  2733. }
  2734. break;
  2735. }
  2736. return nsAutoString(eventName);
  2737. }
  2738. //////////////////////////////////////////////////////////////
  2739. //
  2740. // Code to deal with paint and event debug prefs.
  2741. //
  2742. //////////////////////////////////////////////////////////////
  2743. struct PrefPair
  2744. {
  2745. const char * name;
  2746. bool value;
  2747. };
  2748. static PrefPair debug_PrefValues[] =
  2749. {
  2750. { "nglayout.debug.crossing_event_dumping", false },
  2751. { "nglayout.debug.event_dumping", false },
  2752. { "nglayout.debug.invalidate_dumping", false },
  2753. { "nglayout.debug.motion_event_dumping", false },
  2754. { "nglayout.debug.paint_dumping", false },
  2755. { "nglayout.debug.paint_flashing", false }
  2756. };
  2757. //////////////////////////////////////////////////////////////
  2758. bool
  2759. nsBaseWidget::debug_GetCachedBoolPref(const char * aPrefName)
  2760. {
  2761. NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null.");
  2762. for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++)
  2763. {
  2764. if (strcmp(debug_PrefValues[i].name, aPrefName) == 0)
  2765. {
  2766. return debug_PrefValues[i].value;
  2767. }
  2768. }
  2769. return false;
  2770. }
  2771. //////////////////////////////////////////////////////////////
  2772. static void debug_SetCachedBoolPref(const char * aPrefName,bool aValue)
  2773. {
  2774. NS_ASSERTION(nullptr != aPrefName,"cmon, pref name is null.");
  2775. for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++)
  2776. {
  2777. if (strcmp(debug_PrefValues[i].name, aPrefName) == 0)
  2778. {
  2779. debug_PrefValues[i].value = aValue;
  2780. return;
  2781. }
  2782. }
  2783. NS_ASSERTION(false, "cmon, this code is not reached dude.");
  2784. }
  2785. //////////////////////////////////////////////////////////////
  2786. class Debug_PrefObserver final : public nsIObserver {
  2787. ~Debug_PrefObserver() {}
  2788. public:
  2789. NS_DECL_ISUPPORTS
  2790. NS_DECL_NSIOBSERVER
  2791. };
  2792. NS_IMPL_ISUPPORTS(Debug_PrefObserver, nsIObserver)
  2793. NS_IMETHODIMP
  2794. Debug_PrefObserver::Observe(nsISupports* subject, const char* topic,
  2795. const char16_t* data)
  2796. {
  2797. NS_ConvertUTF16toUTF8 prefName(data);
  2798. bool value = Preferences::GetBool(prefName.get(), false);
  2799. debug_SetCachedBoolPref(prefName.get(), value);
  2800. return NS_OK;
  2801. }
  2802. //////////////////////////////////////////////////////////////
  2803. /* static */ void
  2804. debug_RegisterPrefCallbacks()
  2805. {
  2806. static bool once = true;
  2807. if (!once) {
  2808. return;
  2809. }
  2810. once = false;
  2811. nsCOMPtr<nsIObserver> obs(new Debug_PrefObserver());
  2812. for (uint32_t i = 0; i < ArrayLength(debug_PrefValues); i++) {
  2813. // Initialize the pref values
  2814. debug_PrefValues[i].value =
  2815. Preferences::GetBool(debug_PrefValues[i].name, false);
  2816. if (obs) {
  2817. // Register callbacks for when these change
  2818. Preferences::AddStrongObserver(obs, debug_PrefValues[i].name);
  2819. }
  2820. }
  2821. }
  2822. //////////////////////////////////////////////////////////////
  2823. static int32_t
  2824. _GetPrintCount()
  2825. {
  2826. static int32_t sCount = 0;
  2827. return ++sCount;
  2828. }
  2829. //////////////////////////////////////////////////////////////
  2830. /* static */ bool
  2831. nsBaseWidget::debug_WantPaintFlashing()
  2832. {
  2833. return debug_GetCachedBoolPref("nglayout.debug.paint_flashing");
  2834. }
  2835. //////////////////////////////////////////////////////////////
  2836. /* static */ void
  2837. nsBaseWidget::debug_DumpEvent(FILE * aFileOut,
  2838. nsIWidget * aWidget,
  2839. WidgetGUIEvent* aGuiEvent,
  2840. const char* aWidgetName,
  2841. int32_t aWindowID)
  2842. {
  2843. if (aGuiEvent->mMessage == eMouseMove) {
  2844. if (!debug_GetCachedBoolPref("nglayout.debug.motion_event_dumping"))
  2845. return;
  2846. }
  2847. if (aGuiEvent->mMessage == eMouseEnterIntoWidget ||
  2848. aGuiEvent->mMessage == eMouseExitFromWidget) {
  2849. if (!debug_GetCachedBoolPref("nglayout.debug.crossing_event_dumping"))
  2850. return;
  2851. }
  2852. if (!debug_GetCachedBoolPref("nglayout.debug.event_dumping"))
  2853. return;
  2854. NS_LossyConvertUTF16toASCII tempString(debug_GuiEventToString(aGuiEvent).get());
  2855. fprintf(aFileOut,
  2856. "%4d %-26s widget=%-8p name=%-12s id=0x%-6x refpt=%d,%d\n",
  2857. _GetPrintCount(),
  2858. tempString.get(),
  2859. (void *) aWidget,
  2860. aWidgetName,
  2861. aWindowID,
  2862. aGuiEvent->mRefPoint.x,
  2863. aGuiEvent->mRefPoint.y);
  2864. }
  2865. //////////////////////////////////////////////////////////////
  2866. /* static */ void
  2867. nsBaseWidget::debug_DumpPaintEvent(FILE * aFileOut,
  2868. nsIWidget * aWidget,
  2869. const nsIntRegion & aRegion,
  2870. const char * aWidgetName,
  2871. int32_t aWindowID)
  2872. {
  2873. NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE");
  2874. NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null");
  2875. if (!debug_GetCachedBoolPref("nglayout.debug.paint_dumping"))
  2876. return;
  2877. nsIntRect rect = aRegion.GetBounds();
  2878. fprintf(aFileOut,
  2879. "%4d PAINT widget=%p name=%-12s id=0x%-6x bounds-rect=%3d,%-3d %3d,%-3d",
  2880. _GetPrintCount(),
  2881. (void *) aWidget,
  2882. aWidgetName,
  2883. aWindowID,
  2884. rect.x, rect.y, rect.width, rect.height
  2885. );
  2886. fprintf(aFileOut,"\n");
  2887. }
  2888. //////////////////////////////////////////////////////////////
  2889. /* static */ void
  2890. nsBaseWidget::debug_DumpInvalidate(FILE* aFileOut,
  2891. nsIWidget* aWidget,
  2892. const LayoutDeviceIntRect* aRect,
  2893. const char* aWidgetName,
  2894. int32_t aWindowID)
  2895. {
  2896. if (!debug_GetCachedBoolPref("nglayout.debug.invalidate_dumping"))
  2897. return;
  2898. NS_ASSERTION(nullptr != aFileOut,"cmon, null output FILE");
  2899. NS_ASSERTION(nullptr != aWidget,"cmon, the widget is null");
  2900. fprintf(aFileOut,
  2901. "%4d Invalidate widget=%p name=%-12s id=0x%-6x",
  2902. _GetPrintCount(),
  2903. (void *) aWidget,
  2904. aWidgetName,
  2905. aWindowID);
  2906. if (aRect) {
  2907. fprintf(aFileOut,
  2908. " rect=%3d,%-3d %3d,%-3d",
  2909. aRect->x, aRect->y, aRect->width, aRect->height);
  2910. } else {
  2911. fprintf(aFileOut,
  2912. " rect=%-15s",
  2913. "none");
  2914. }
  2915. fprintf(aFileOut, "\n");
  2916. }
  2917. //////////////////////////////////////////////////////////////
  2918. #endif // DEBUG