PuppetWidget.cpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. * vim: sw=2 ts=8 et :
  3. */
  4. /* This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  7. #include "base/basictypes.h"
  8. #include "ClientLayerManager.h"
  9. #include "gfxPlatform.h"
  10. #include "mozilla/dom/TabChild.h"
  11. #include "mozilla/Hal.h"
  12. #include "mozilla/IMEStateManager.h"
  13. #include "mozilla/layers/APZChild.h"
  14. #include "mozilla/layers/PLayerTransactionChild.h"
  15. #include "mozilla/Preferences.h"
  16. #include "mozilla/TextComposition.h"
  17. #include "mozilla/TextEvents.h"
  18. #include "mozilla/Unused.h"
  19. #include "PuppetWidget.h"
  20. #include "nsContentUtils.h"
  21. #include "nsIWidgetListener.h"
  22. #include "imgIContainer.h"
  23. #include "nsView.h"
  24. using namespace mozilla;
  25. using namespace mozilla::dom;
  26. using namespace mozilla::hal;
  27. using namespace mozilla::gfx;
  28. using namespace mozilla::layers;
  29. using namespace mozilla::widget;
  30. static void
  31. InvalidateRegion(nsIWidget* aWidget, const LayoutDeviceIntRegion& aRegion)
  32. {
  33. for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
  34. aWidget->Invalidate(iter.Get());
  35. }
  36. }
  37. /*static*/ already_AddRefed<nsIWidget>
  38. nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
  39. {
  40. MOZ_ASSERT(!aTabChild || nsIWidget::UsePuppetWidgets(),
  41. "PuppetWidgets not allowed in this configuration");
  42. nsCOMPtr<nsIWidget> widget = new PuppetWidget(aTabChild);
  43. return widget.forget();
  44. }
  45. namespace mozilla {
  46. namespace widget {
  47. static bool
  48. IsPopup(const nsWidgetInitData* aInitData)
  49. {
  50. return aInitData && aInitData->mWindowType == eWindowType_popup;
  51. }
  52. static bool
  53. MightNeedIMEFocus(const nsWidgetInitData* aInitData)
  54. {
  55. // In the puppet-widget world, popup widgets are just dummies and
  56. // shouldn't try to mess with IME state.
  57. #ifdef MOZ_CROSS_PROCESS_IME
  58. return !IsPopup(aInitData);
  59. #else
  60. return false;
  61. #endif
  62. }
  63. // Arbitrary, fungible.
  64. const size_t PuppetWidget::kMaxDimension = 4000;
  65. NS_IMPL_ISUPPORTS_INHERITED0(PuppetWidget, nsBaseWidget)
  66. PuppetWidget::PuppetWidget(TabChild* aTabChild)
  67. : mTabChild(aTabChild)
  68. , mMemoryPressureObserver(nullptr)
  69. , mDPI(-1)
  70. , mRounding(-1)
  71. , mDefaultScale(-1)
  72. , mCursorHotspotX(0)
  73. , mCursorHotspotY(0)
  74. , mNativeKeyCommandsValid(false)
  75. {
  76. MOZ_COUNT_CTOR(PuppetWidget);
  77. mSingleLineCommands.SetCapacity(4);
  78. mMultiLineCommands.SetCapacity(4);
  79. mRichTextCommands.SetCapacity(4);
  80. // Setting 'Unknown' means "not yet cached".
  81. mInputContext.mIMEState.mEnabled = IMEState::UNKNOWN;
  82. }
  83. PuppetWidget::~PuppetWidget()
  84. {
  85. MOZ_COUNT_DTOR(PuppetWidget);
  86. Destroy();
  87. }
  88. void
  89. PuppetWidget::InfallibleCreate(nsIWidget* aParent,
  90. nsNativeWidget aNativeParent,
  91. const LayoutDeviceIntRect& aRect,
  92. nsWidgetInitData* aInitData)
  93. {
  94. MOZ_ASSERT(!aNativeParent, "got a non-Puppet native parent");
  95. BaseCreate(nullptr, aInitData);
  96. mBounds = aRect;
  97. mEnabled = true;
  98. mVisible = true;
  99. mDrawTarget = gfxPlatform::GetPlatform()->
  100. CreateOffscreenContentDrawTarget(IntSize(1, 1), SurfaceFormat::B8G8R8A8);
  101. mNeedIMEStateInit = MightNeedIMEFocus(aInitData);
  102. PuppetWidget* parent = static_cast<PuppetWidget*>(aParent);
  103. if (parent) {
  104. parent->SetChild(this);
  105. mLayerManager = parent->GetLayerManager();
  106. }
  107. else {
  108. Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
  109. }
  110. nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  111. if (obs) {
  112. mMemoryPressureObserver = new MemoryPressureObserver(this);
  113. obs->AddObserver(mMemoryPressureObserver, "memory-pressure", false);
  114. }
  115. }
  116. nsresult
  117. PuppetWidget::Create(nsIWidget* aParent,
  118. nsNativeWidget aNativeParent,
  119. const LayoutDeviceIntRect& aRect,
  120. nsWidgetInitData* aInitData)
  121. {
  122. InfallibleCreate(aParent, aNativeParent, aRect, aInitData);
  123. return NS_OK;
  124. }
  125. void
  126. PuppetWidget::InitIMEState()
  127. {
  128. MOZ_ASSERT(mTabChild);
  129. if (mNeedIMEStateInit) {
  130. mContentCache.Clear();
  131. mTabChild->SendUpdateContentCache(mContentCache);
  132. mIMEPreferenceOfParent = nsIMEUpdatePreference();
  133. mNeedIMEStateInit = false;
  134. }
  135. }
  136. already_AddRefed<nsIWidget>
  137. PuppetWidget::CreateChild(const LayoutDeviceIntRect& aRect,
  138. nsWidgetInitData* aInitData,
  139. bool aForceUseIWidgetParent)
  140. {
  141. bool isPopup = IsPopup(aInitData);
  142. nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(mTabChild);
  143. return ((widget &&
  144. NS_SUCCEEDED(widget->Create(isPopup ? nullptr: this, nullptr, aRect,
  145. aInitData))) ?
  146. widget.forget() : nullptr);
  147. }
  148. void
  149. PuppetWidget::Destroy()
  150. {
  151. if (mOnDestroyCalled) {
  152. return;
  153. }
  154. mOnDestroyCalled = true;
  155. Base::OnDestroy();
  156. Base::Destroy();
  157. mPaintTask.Revoke();
  158. if (mMemoryPressureObserver) {
  159. mMemoryPressureObserver->Remove();
  160. }
  161. mMemoryPressureObserver = nullptr;
  162. mChild = nullptr;
  163. if (mLayerManager) {
  164. mLayerManager->Destroy();
  165. }
  166. mLayerManager = nullptr;
  167. mTabChild = nullptr;
  168. }
  169. NS_IMETHODIMP
  170. PuppetWidget::Show(bool aState)
  171. {
  172. NS_ASSERTION(mEnabled,
  173. "does it make sense to Show()/Hide() a disabled widget?");
  174. bool wasVisible = mVisible;
  175. mVisible = aState;
  176. if (mChild) {
  177. mChild->mVisible = aState;
  178. }
  179. if (!wasVisible && mVisible) {
  180. // The previously attached widget listener is handy if
  181. // we're transitioning from page to page without dropping
  182. // layers (since we'll continue to show the old layers
  183. // associated with that old widget listener). If the
  184. // PuppetWidget was hidden, those layers are dropped,
  185. // so the previously attached widget listener is really
  186. // of no use anymore (and is actually actively harmful - see
  187. // bug 1323586).
  188. mPreviouslyAttachedWidgetListener = nullptr;
  189. Resize(mBounds.width, mBounds.height, false);
  190. Invalidate(mBounds);
  191. }
  192. return NS_OK;
  193. }
  194. NS_IMETHODIMP
  195. PuppetWidget::Resize(double aWidth,
  196. double aHeight,
  197. bool aRepaint)
  198. {
  199. LayoutDeviceIntRect oldBounds = mBounds;
  200. mBounds.SizeTo(LayoutDeviceIntSize(NSToIntRound(aWidth),
  201. NSToIntRound(aHeight)));
  202. if (mChild) {
  203. return mChild->Resize(aWidth, aHeight, aRepaint);
  204. }
  205. // XXX: roc says that |aRepaint| dictates whether or not to
  206. // invalidate the expanded area
  207. if (oldBounds.Size() < mBounds.Size() && aRepaint) {
  208. LayoutDeviceIntRegion dirty(mBounds);
  209. dirty.Sub(dirty, oldBounds);
  210. InvalidateRegion(this, dirty);
  211. }
  212. // call WindowResized() on both the current listener, and possibly
  213. // also the previous one if we're in a state where we're drawing that one
  214. // because the current one is paint suppressed
  215. if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) {
  216. if (GetCurrentWidgetListener() &&
  217. GetCurrentWidgetListener() != mAttachedWidgetListener) {
  218. GetCurrentWidgetListener()->WindowResized(this, mBounds.width, mBounds.height);
  219. }
  220. mAttachedWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
  221. }
  222. return NS_OK;
  223. }
  224. nsresult
  225. PuppetWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
  226. {
  227. for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
  228. const Configuration& configuration = aConfigurations[i];
  229. PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild.get());
  230. NS_ASSERTION(w->GetParent() == this,
  231. "Configured widget is not a child");
  232. w->SetWindowClipRegion(configuration.mClipRegion, true);
  233. LayoutDeviceIntRect bounds = w->GetBounds();
  234. if (bounds.Size() != configuration.mBounds.Size()) {
  235. w->Resize(configuration.mBounds.x, configuration.mBounds.y,
  236. configuration.mBounds.width, configuration.mBounds.height,
  237. true);
  238. } else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
  239. w->Move(configuration.mBounds.x, configuration.mBounds.y);
  240. }
  241. w->SetWindowClipRegion(configuration.mClipRegion, false);
  242. }
  243. return NS_OK;
  244. }
  245. NS_IMETHODIMP
  246. PuppetWidget::SetFocus(bool aRaise)
  247. {
  248. if (aRaise && mTabChild) {
  249. mTabChild->SendRequestFocus(true);
  250. }
  251. return NS_OK;
  252. }
  253. NS_IMETHODIMP
  254. PuppetWidget::Invalidate(const LayoutDeviceIntRect& aRect)
  255. {
  256. #ifdef DEBUG
  257. debug_DumpInvalidate(stderr, this, &aRect, "PuppetWidget", 0);
  258. #endif
  259. if (mChild) {
  260. return mChild->Invalidate(aRect);
  261. }
  262. mDirtyRegion.Or(mDirtyRegion, aRect);
  263. if (!mDirtyRegion.IsEmpty() && !mPaintTask.IsPending()) {
  264. mPaintTask = new PaintTask(this);
  265. return NS_DispatchToCurrentThread(mPaintTask.get());
  266. }
  267. return NS_OK;
  268. }
  269. void
  270. PuppetWidget::InitEvent(WidgetGUIEvent& event, LayoutDeviceIntPoint* aPoint)
  271. {
  272. if (nullptr == aPoint) {
  273. event.mRefPoint = LayoutDeviceIntPoint(0, 0);
  274. } else {
  275. // use the point override if provided
  276. event.mRefPoint = *aPoint;
  277. }
  278. event.mTime = PR_Now() / 1000;
  279. }
  280. NS_IMETHODIMP
  281. PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
  282. {
  283. #ifdef DEBUG
  284. debug_DumpEvent(stdout, event->mWidget, event, "PuppetWidget", 0);
  285. #endif
  286. MOZ_ASSERT(!mChild || mChild->mWindowType == eWindowType_popup,
  287. "Unexpected event dispatch!");
  288. AutoCacheNativeKeyCommands autoCache(this);
  289. if (event->mFlags.mIsSynthesizedForTests && !mNativeKeyCommandsValid) {
  290. WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
  291. if (keyEvent) {
  292. mTabChild->RequestNativeKeyBindings(&autoCache, keyEvent);
  293. }
  294. }
  295. if (event->mClass == eCompositionEventClass) {
  296. // Store the latest native IME context of parent process's widget or
  297. // TextEventDispatcher if it's in this process.
  298. WidgetCompositionEvent* compositionEvent = event->AsCompositionEvent();
  299. #ifdef DEBUG
  300. if (mNativeIMEContext.IsValid() &&
  301. mNativeIMEContext != compositionEvent->mNativeIMEContext) {
  302. RefPtr<TextComposition> composition =
  303. IMEStateManager::GetTextCompositionFor(this);
  304. MOZ_ASSERT(!composition,
  305. "When there is composition caused by old native IME context, "
  306. "composition events caused by different native IME context are not "
  307. "allowed");
  308. }
  309. #endif // #ifdef DEBUG
  310. mNativeIMEContext = compositionEvent->mNativeIMEContext;
  311. }
  312. aStatus = nsEventStatus_eIgnore;
  313. if (GetCurrentWidgetListener()) {
  314. aStatus = GetCurrentWidgetListener()->HandleEvent(event, mUseAttachedEvents);
  315. }
  316. return NS_OK;
  317. }
  318. nsEventStatus
  319. PuppetWidget::DispatchInputEvent(WidgetInputEvent* aEvent)
  320. {
  321. if (!AsyncPanZoomEnabled()) {
  322. nsEventStatus status = nsEventStatus_eIgnore;
  323. DispatchEvent(aEvent, status);
  324. return status;
  325. }
  326. if (!mTabChild) {
  327. return nsEventStatus_eIgnore;
  328. }
  329. switch (aEvent->mClass) {
  330. case eWheelEventClass:
  331. Unused <<
  332. mTabChild->SendDispatchWheelEvent(*aEvent->AsWheelEvent());
  333. break;
  334. case eMouseEventClass:
  335. Unused <<
  336. mTabChild->SendDispatchMouseEvent(*aEvent->AsMouseEvent());
  337. break;
  338. case eKeyboardEventClass:
  339. Unused <<
  340. mTabChild->SendDispatchKeyboardEvent(*aEvent->AsKeyboardEvent());
  341. break;
  342. default:
  343. MOZ_ASSERT_UNREACHABLE("unsupported event type");
  344. }
  345. return nsEventStatus_eIgnore;
  346. }
  347. nsresult
  348. PuppetWidget::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
  349. int32_t aNativeKeyCode,
  350. uint32_t aModifierFlags,
  351. const nsAString& aCharacters,
  352. const nsAString& aUnmodifiedCharacters,
  353. nsIObserver* aObserver)
  354. {
  355. AutoObserverNotifier notifier(aObserver, "keyevent");
  356. if (!mTabChild) {
  357. return NS_ERROR_FAILURE;
  358. }
  359. mTabChild->SendSynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode,
  360. aModifierFlags, nsString(aCharacters), nsString(aUnmodifiedCharacters),
  361. notifier.SaveObserver());
  362. return NS_OK;
  363. }
  364. nsresult
  365. PuppetWidget::SynthesizeNativeMouseEvent(mozilla::LayoutDeviceIntPoint aPoint,
  366. uint32_t aNativeMessage,
  367. uint32_t aModifierFlags,
  368. nsIObserver* aObserver)
  369. {
  370. AutoObserverNotifier notifier(aObserver, "mouseevent");
  371. if (!mTabChild) {
  372. return NS_ERROR_FAILURE;
  373. }
  374. mTabChild->SendSynthesizeNativeMouseEvent(aPoint, aNativeMessage,
  375. aModifierFlags, notifier.SaveObserver());
  376. return NS_OK;
  377. }
  378. nsresult
  379. PuppetWidget::SynthesizeNativeMouseMove(mozilla::LayoutDeviceIntPoint aPoint,
  380. nsIObserver* aObserver)
  381. {
  382. AutoObserverNotifier notifier(aObserver, "mousemove");
  383. if (!mTabChild) {
  384. return NS_ERROR_FAILURE;
  385. }
  386. mTabChild->SendSynthesizeNativeMouseMove(aPoint, notifier.SaveObserver());
  387. return NS_OK;
  388. }
  389. nsresult
  390. PuppetWidget::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
  391. uint32_t aNativeMessage,
  392. double aDeltaX,
  393. double aDeltaY,
  394. double aDeltaZ,
  395. uint32_t aModifierFlags,
  396. uint32_t aAdditionalFlags,
  397. nsIObserver* aObserver)
  398. {
  399. AutoObserverNotifier notifier(aObserver, "mousescrollevent");
  400. if (!mTabChild) {
  401. return NS_ERROR_FAILURE;
  402. }
  403. mTabChild->SendSynthesizeNativeMouseScrollEvent(aPoint, aNativeMessage,
  404. aDeltaX, aDeltaY, aDeltaZ, aModifierFlags, aAdditionalFlags,
  405. notifier.SaveObserver());
  406. return NS_OK;
  407. }
  408. nsresult
  409. PuppetWidget::SynthesizeNativeTouchPoint(uint32_t aPointerId,
  410. TouchPointerState aPointerState,
  411. LayoutDeviceIntPoint aPoint,
  412. double aPointerPressure,
  413. uint32_t aPointerOrientation,
  414. nsIObserver* aObserver)
  415. {
  416. AutoObserverNotifier notifier(aObserver, "touchpoint");
  417. if (!mTabChild) {
  418. return NS_ERROR_FAILURE;
  419. }
  420. mTabChild->SendSynthesizeNativeTouchPoint(aPointerId, aPointerState,
  421. aPoint, aPointerPressure, aPointerOrientation,
  422. notifier.SaveObserver());
  423. return NS_OK;
  424. }
  425. nsresult
  426. PuppetWidget::SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint,
  427. bool aLongTap,
  428. nsIObserver* aObserver)
  429. {
  430. AutoObserverNotifier notifier(aObserver, "touchtap");
  431. if (!mTabChild) {
  432. return NS_ERROR_FAILURE;
  433. }
  434. mTabChild->SendSynthesizeNativeTouchTap(aPoint, aLongTap,
  435. notifier.SaveObserver());
  436. return NS_OK;
  437. }
  438. nsresult
  439. PuppetWidget::ClearNativeTouchSequence(nsIObserver* aObserver)
  440. {
  441. AutoObserverNotifier notifier(aObserver, "cleartouch");
  442. if (!mTabChild) {
  443. return NS_ERROR_FAILURE;
  444. }
  445. mTabChild->SendClearNativeTouchSequence(notifier.SaveObserver());
  446. return NS_OK;
  447. }
  448. void
  449. PuppetWidget::SetConfirmedTargetAPZC(uint64_t aInputBlockId,
  450. const nsTArray<ScrollableLayerGuid>& aTargets) const
  451. {
  452. if (mTabChild) {
  453. mTabChild->SetTargetAPZC(aInputBlockId, aTargets);
  454. }
  455. }
  456. void
  457. PuppetWidget::UpdateZoomConstraints(const uint32_t& aPresShellId,
  458. const FrameMetrics::ViewID& aViewId,
  459. const Maybe<ZoomConstraints>& aConstraints)
  460. {
  461. if (mTabChild) {
  462. mTabChild->DoUpdateZoomConstraints(aPresShellId, aViewId, aConstraints);
  463. }
  464. }
  465. bool
  466. PuppetWidget::AsyncPanZoomEnabled() const
  467. {
  468. return mTabChild && mTabChild->AsyncPanZoomEnabled();
  469. }
  470. NS_IMETHODIMP_(bool)
  471. PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
  472. const mozilla::WidgetKeyboardEvent& aEvent,
  473. DoCommandCallback aCallback,
  474. void* aCallbackData)
  475. {
  476. AutoCacheNativeKeyCommands autoCache(this);
  477. if (!aEvent.mWidget && !mNativeKeyCommandsValid) {
  478. MOZ_ASSERT(!aEvent.mFlags.mIsSynthesizedForTests);
  479. // Abort if untrusted to avoid leaking system settings
  480. if (NS_WARN_IF(!aEvent.IsTrusted())) {
  481. return false;
  482. }
  483. mTabChild->RequestNativeKeyBindings(&autoCache, &aEvent);
  484. }
  485. MOZ_ASSERT(mNativeKeyCommandsValid);
  486. const nsTArray<mozilla::CommandInt>* commands = nullptr;
  487. switch (aType) {
  488. case nsIWidget::NativeKeyBindingsForSingleLineEditor:
  489. commands = &mSingleLineCommands;
  490. break;
  491. case nsIWidget::NativeKeyBindingsForMultiLineEditor:
  492. commands = &mMultiLineCommands;
  493. break;
  494. case nsIWidget::NativeKeyBindingsForRichTextEditor:
  495. commands = &mRichTextCommands;
  496. break;
  497. default:
  498. MOZ_CRASH("Invalid type");
  499. break;
  500. }
  501. if (commands->IsEmpty()) {
  502. return false;
  503. }
  504. for (uint32_t i = 0; i < commands->Length(); i++) {
  505. aCallback(static_cast<mozilla::Command>((*commands)[i]), aCallbackData);
  506. }
  507. return true;
  508. }
  509. LayerManager*
  510. PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
  511. LayersBackend aBackendHint,
  512. LayerManagerPersistence aPersistence)
  513. {
  514. if (!mLayerManager) {
  515. mLayerManager = new ClientLayerManager(this);
  516. }
  517. ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder();
  518. if (lf && !lf->HasShadowManager() && aShadowManager) {
  519. lf->SetShadowManager(aShadowManager);
  520. }
  521. return mLayerManager;
  522. }
  523. LayerManager*
  524. PuppetWidget::RecreateLayerManager(PLayerTransactionChild* aShadowManager)
  525. {
  526. mLayerManager = new ClientLayerManager(this);
  527. if (ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder()) {
  528. lf->SetShadowManager(aShadowManager);
  529. }
  530. return mLayerManager;
  531. }
  532. nsresult
  533. PuppetWidget::RequestIMEToCommitComposition(bool aCancel)
  534. {
  535. #ifdef MOZ_CROSS_PROCESS_IME
  536. if (!mTabChild) {
  537. return NS_ERROR_FAILURE;
  538. }
  539. MOZ_ASSERT(!Destroyed());
  540. // There must not be composition which is caused by the PuppetWidget instance.
  541. if (NS_WARN_IF(!mNativeIMEContext.IsValid())) {
  542. return NS_OK;
  543. }
  544. RefPtr<TextComposition> composition =
  545. IMEStateManager::GetTextCompositionFor(this);
  546. // This method shouldn't be called when there is no text composition instance.
  547. if (NS_WARN_IF(!composition)) {
  548. return NS_OK;
  549. }
  550. bool isCommitted = false;
  551. nsAutoString committedString;
  552. if (NS_WARN_IF(!mTabChild->SendRequestIMEToCommitComposition(
  553. aCancel, &isCommitted, &committedString))) {
  554. return NS_ERROR_FAILURE;
  555. }
  556. // If the composition wasn't committed synchronously, we need to wait async
  557. // composition events for destroying the TextComposition instance.
  558. if (!isCommitted) {
  559. return NS_OK;
  560. }
  561. // Dispatch eCompositionCommit event.
  562. WidgetCompositionEvent compositionCommitEvent(true, eCompositionCommit, this);
  563. InitEvent(compositionCommitEvent, nullptr);
  564. compositionCommitEvent.mData = committedString;
  565. nsEventStatus status = nsEventStatus_eIgnore;
  566. DispatchEvent(&compositionCommitEvent, status);
  567. // NOTE: PuppetWidget might be destroyed already.
  568. #endif // #ifdef MOZ_CROSS_PROCESS_IME
  569. return NS_OK;
  570. }
  571. nsresult
  572. PuppetWidget::NotifyIMEInternal(const IMENotification& aIMENotification)
  573. {
  574. switch (aIMENotification.mMessage) {
  575. case REQUEST_TO_COMMIT_COMPOSITION:
  576. return RequestIMEToCommitComposition(false);
  577. case REQUEST_TO_CANCEL_COMPOSITION:
  578. return RequestIMEToCommitComposition(true);
  579. case NOTIFY_IME_OF_FOCUS:
  580. case NOTIFY_IME_OF_BLUR:
  581. return NotifyIMEOfFocusChange(aIMENotification);
  582. case NOTIFY_IME_OF_SELECTION_CHANGE:
  583. return NotifyIMEOfSelectionChange(aIMENotification);
  584. case NOTIFY_IME_OF_TEXT_CHANGE:
  585. return NotifyIMEOfTextChange(aIMENotification);
  586. case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED:
  587. return NotifyIMEOfCompositionUpdate(aIMENotification);
  588. case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
  589. return NotifyIMEOfMouseButtonEvent(aIMENotification);
  590. case NOTIFY_IME_OF_POSITION_CHANGE:
  591. return NotifyIMEOfPositionChange(aIMENotification);
  592. default:
  593. return NS_ERROR_NOT_IMPLEMENTED;
  594. }
  595. }
  596. NS_IMETHODIMP
  597. PuppetWidget::StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent,
  598. int32_t aPanelX, int32_t aPanelY,
  599. nsString& aCommitted)
  600. {
  601. if (!mTabChild ||
  602. !mTabChild->SendStartPluginIME(aKeyboardEvent, aPanelX,
  603. aPanelY, &aCommitted)) {
  604. return NS_ERROR_FAILURE;
  605. }
  606. return NS_OK;
  607. }
  608. void
  609. PuppetWidget::SetPluginFocused(bool& aFocused)
  610. {
  611. if (mTabChild) {
  612. mTabChild->SendSetPluginFocused(aFocused);
  613. }
  614. }
  615. void
  616. PuppetWidget::DefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent)
  617. {
  618. if (!mTabChild) {
  619. return;
  620. }
  621. mTabChild->SendDefaultProcOfPluginEvent(aEvent);
  622. }
  623. NS_IMETHODIMP_(void)
  624. PuppetWidget::SetInputContext(const InputContext& aContext,
  625. const InputContextAction& aAction)
  626. {
  627. mInputContext = aContext;
  628. // Any widget instances cannot cache IME open state because IME open state
  629. // can be changed by user but native IME may not notify us of changing the
  630. // open state on some platforms.
  631. mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
  632. #ifndef MOZ_CROSS_PROCESS_IME
  633. return;
  634. #endif
  635. if (!mTabChild) {
  636. return;
  637. }
  638. mTabChild->SendSetInputContext(
  639. static_cast<int32_t>(aContext.mIMEState.mEnabled),
  640. static_cast<int32_t>(aContext.mIMEState.mOpen),
  641. aContext.mHTMLInputType,
  642. aContext.mHTMLInputInputmode,
  643. aContext.mActionHint,
  644. static_cast<int32_t>(aAction.mCause),
  645. static_cast<int32_t>(aAction.mFocusChange));
  646. }
  647. NS_IMETHODIMP_(InputContext)
  648. PuppetWidget::GetInputContext()
  649. {
  650. #ifndef MOZ_CROSS_PROCESS_IME
  651. return InputContext();
  652. #endif
  653. // XXX Currently, we don't support retrieving IME open state from child
  654. // process.
  655. // When this widget caches input context and currently managed by
  656. // IMEStateManager, the cache is valid. Only in this case, we can
  657. // avoid to use synchronous IPC.
  658. if (mInputContext.mIMEState.mEnabled != IMEState::UNKNOWN &&
  659. IMEStateManager::GetWidgetForActiveInputContext() == this) {
  660. return mInputContext;
  661. }
  662. NS_WARNING("PuppetWidget::GetInputContext() needs to retrieve it with IPC");
  663. // Don't cache InputContext here because this process isn't managing IME
  664. // state of the chrome widget. So, we cannot modify mInputContext when
  665. // chrome widget is set to new context.
  666. InputContext context;
  667. if (mTabChild) {
  668. int32_t enabled, open;
  669. mTabChild->SendGetInputContext(&enabled, &open);
  670. context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(enabled);
  671. context.mIMEState.mOpen = static_cast<IMEState::Open>(open);
  672. }
  673. return context;
  674. }
  675. NS_IMETHODIMP_(NativeIMEContext)
  676. PuppetWidget::GetNativeIMEContext()
  677. {
  678. return mNativeIMEContext;
  679. }
  680. nsresult
  681. PuppetWidget::NotifyIMEOfFocusChange(const IMENotification& aIMENotification)
  682. {
  683. #ifndef MOZ_CROSS_PROCESS_IME
  684. return NS_OK;
  685. #endif
  686. if (!mTabChild)
  687. return NS_ERROR_FAILURE;
  688. bool gotFocus = aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS;
  689. if (gotFocus) {
  690. if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN) {
  691. // When IME gets focus, we should initalize all information of the
  692. // content.
  693. if (NS_WARN_IF(!mContentCache.CacheAll(this, &aIMENotification))) {
  694. return NS_ERROR_FAILURE;
  695. }
  696. } else {
  697. // However, if a plugin has focus, only the editor rect information is
  698. // available.
  699. if (NS_WARN_IF(!mContentCache.CacheEditorRect(this, &aIMENotification))) {
  700. return NS_ERROR_FAILURE;
  701. }
  702. }
  703. } else {
  704. // When IME loses focus, we don't need to store anything.
  705. mContentCache.Clear();
  706. }
  707. mIMEPreferenceOfParent = nsIMEUpdatePreference();
  708. if (!mTabChild->SendNotifyIMEFocus(mContentCache, aIMENotification,
  709. &mIMEPreferenceOfParent)) {
  710. return NS_ERROR_FAILURE;
  711. }
  712. return NS_OK;
  713. }
  714. nsresult
  715. PuppetWidget::NotifyIMEOfCompositionUpdate(
  716. const IMENotification& aIMENotification)
  717. {
  718. #ifndef MOZ_CROSS_PROCESS_IME
  719. return NS_OK;
  720. #endif
  721. NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
  722. if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
  723. NS_WARN_IF(!mContentCache.CacheSelection(this, &aIMENotification))) {
  724. return NS_ERROR_FAILURE;
  725. }
  726. mTabChild->SendNotifyIMECompositionUpdate(mContentCache, aIMENotification);
  727. return NS_OK;
  728. }
  729. nsIMEUpdatePreference
  730. PuppetWidget::GetIMEUpdatePreference()
  731. {
  732. #ifdef MOZ_CROSS_PROCESS_IME
  733. // e10s requires IME content cache in in the TabParent for handling query
  734. // content event only with the parent process. Therefore, this process
  735. // needs to receive a lot of information from the focused editor to sent
  736. // the latest content to the parent process.
  737. if (mInputContext.mIMEState.mEnabled == IMEState::PLUGIN) {
  738. // But if a plugin has focus, we cannot receive text nor selection change
  739. // in the plugin. Therefore, PuppetWidget needs to receive only position
  740. // change event for updating the editor rect cache.
  741. return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
  742. nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE);
  743. }
  744. return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
  745. nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
  746. nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE );
  747. #else
  748. // B2G doesn't handle IME as widget-level.
  749. return nsIMEUpdatePreference();
  750. #endif
  751. }
  752. nsresult
  753. PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
  754. {
  755. MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
  756. "Passed wrong notification");
  757. #ifndef MOZ_CROSS_PROCESS_IME
  758. return NS_OK;
  759. #endif
  760. if (!mTabChild)
  761. return NS_ERROR_FAILURE;
  762. // While a plugin has focus, text change notification shouldn't be available.
  763. if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
  764. return NS_ERROR_FAILURE;
  765. }
  766. // FYI: text change notification is the first notification after
  767. // a user operation changes the content. So, we need to modify
  768. // the cache as far as possible here.
  769. if (NS_WARN_IF(!mContentCache.CacheText(this, &aIMENotification))) {
  770. return NS_ERROR_FAILURE;
  771. }
  772. // TabParent doesn't this this to cache. we don't send the notification
  773. // if parent process doesn't request NOTIFY_TEXT_CHANGE.
  774. if (mIMEPreferenceOfParent.WantTextChange()) {
  775. mTabChild->SendNotifyIMETextChange(mContentCache, aIMENotification);
  776. } else {
  777. mTabChild->SendUpdateContentCache(mContentCache);
  778. }
  779. return NS_OK;
  780. }
  781. nsresult
  782. PuppetWidget::NotifyIMEOfSelectionChange(
  783. const IMENotification& aIMENotification)
  784. {
  785. MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE,
  786. "Passed wrong notification");
  787. #ifndef MOZ_CROSS_PROCESS_IME
  788. return NS_OK;
  789. #endif
  790. if (!mTabChild)
  791. return NS_ERROR_FAILURE;
  792. // While a plugin has focus, selection change notification shouldn't be
  793. // available.
  794. if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
  795. return NS_ERROR_FAILURE;
  796. }
  797. // Note that selection change must be notified after text change if it occurs.
  798. // Therefore, we don't need to query text content again here.
  799. mContentCache.SetSelection(
  800. this,
  801. aIMENotification.mSelectionChangeData.mOffset,
  802. aIMENotification.mSelectionChangeData.Length(),
  803. aIMENotification.mSelectionChangeData.mReversed,
  804. aIMENotification.mSelectionChangeData.GetWritingMode());
  805. mTabChild->SendNotifyIMESelection(mContentCache, aIMENotification);
  806. return NS_OK;
  807. }
  808. nsresult
  809. PuppetWidget::NotifyIMEOfMouseButtonEvent(
  810. const IMENotification& aIMENotification)
  811. {
  812. if (!mTabChild) {
  813. return NS_ERROR_FAILURE;
  814. }
  815. // While a plugin has focus, mouse button event notification shouldn't be
  816. // available.
  817. if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
  818. return NS_ERROR_FAILURE;
  819. }
  820. bool consumedByIME = false;
  821. if (!mTabChild->SendNotifyIMEMouseButtonEvent(aIMENotification,
  822. &consumedByIME)) {
  823. return NS_ERROR_FAILURE;
  824. }
  825. return consumedByIME ? NS_SUCCESS_EVENT_CONSUMED : NS_OK;
  826. }
  827. nsresult
  828. PuppetWidget::NotifyIMEOfPositionChange(const IMENotification& aIMENotification)
  829. {
  830. #ifndef MOZ_CROSS_PROCESS_IME
  831. return NS_OK;
  832. #endif
  833. if (NS_WARN_IF(!mTabChild)) {
  834. return NS_ERROR_FAILURE;
  835. }
  836. if (NS_WARN_IF(!mContentCache.CacheEditorRect(this, &aIMENotification))) {
  837. return NS_ERROR_FAILURE;
  838. }
  839. // While a plugin has focus, selection range isn't available. So, we don't
  840. // need to cache it at that time.
  841. if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
  842. NS_WARN_IF(!mContentCache.CacheSelection(this, &aIMENotification))) {
  843. return NS_ERROR_FAILURE;
  844. }
  845. if (mIMEPreferenceOfParent.WantPositionChanged()) {
  846. mTabChild->SendNotifyIMEPositionChange(mContentCache, aIMENotification);
  847. } else {
  848. mTabChild->SendUpdateContentCache(mContentCache);
  849. }
  850. return NS_OK;
  851. }
  852. NS_IMETHODIMP
  853. PuppetWidget::SetCursor(nsCursor aCursor)
  854. {
  855. // Don't cache on windows, Windowless flash breaks this via async cursor updates.
  856. #if !defined(XP_WIN)
  857. if (mCursor == aCursor && !mCustomCursor && !mUpdateCursor) {
  858. return NS_OK;
  859. }
  860. #endif
  861. mCustomCursor = nullptr;
  862. if (mTabChild &&
  863. !mTabChild->SendSetCursor(aCursor, mUpdateCursor)) {
  864. return NS_ERROR_FAILURE;
  865. }
  866. mCursor = aCursor;
  867. mUpdateCursor = false;
  868. return NS_OK;
  869. }
  870. NS_IMETHODIMP
  871. PuppetWidget::SetCursor(imgIContainer* aCursor,
  872. uint32_t aHotspotX, uint32_t aHotspotY)
  873. {
  874. if (!aCursor || !mTabChild) {
  875. return NS_OK;
  876. }
  877. #if !defined(XP_WIN)
  878. if (mCustomCursor == aCursor &&
  879. mCursorHotspotX == aHotspotX &&
  880. mCursorHotspotY == aHotspotY &&
  881. !mUpdateCursor) {
  882. return NS_OK;
  883. }
  884. #endif
  885. RefPtr<mozilla::gfx::SourceSurface> surface =
  886. aCursor->GetFrame(imgIContainer::FRAME_CURRENT,
  887. imgIContainer::FLAG_SYNC_DECODE);
  888. if (!surface) {
  889. return NS_ERROR_FAILURE;
  890. }
  891. RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
  892. surface->GetDataSurface();
  893. if (!dataSurface) {
  894. return NS_ERROR_FAILURE;
  895. }
  896. size_t length;
  897. int32_t stride;
  898. mozilla::UniquePtr<char[]> surfaceData =
  899. nsContentUtils::GetSurfaceData(WrapNotNull(dataSurface), &length, &stride);
  900. nsDependentCString cursorData(surfaceData.get(), length);
  901. mozilla::gfx::IntSize size = dataSurface->GetSize();
  902. if (!mTabChild->SendSetCustomCursor(cursorData, size.width, size.height, stride,
  903. static_cast<uint8_t>(dataSurface->GetFormat()),
  904. aHotspotX, aHotspotY, mUpdateCursor)) {
  905. return NS_ERROR_FAILURE;
  906. }
  907. mCursor = nsCursor(-1);
  908. mCustomCursor = aCursor;
  909. mCursorHotspotX = aHotspotX;
  910. mCursorHotspotY = aHotspotY;
  911. mUpdateCursor = false;
  912. return NS_OK;
  913. }
  914. void
  915. PuppetWidget::ClearCachedCursor()
  916. {
  917. nsBaseWidget::ClearCachedCursor();
  918. mCustomCursor = nullptr;
  919. }
  920. nsresult
  921. PuppetWidget::Paint()
  922. {
  923. MOZ_ASSERT(!mDirtyRegion.IsEmpty(), "paint event logic messed up");
  924. if (!GetCurrentWidgetListener())
  925. return NS_OK;
  926. LayoutDeviceIntRegion region = mDirtyRegion;
  927. // reset repaint tracking
  928. mDirtyRegion.SetEmpty();
  929. mPaintTask.Revoke();
  930. RefPtr<PuppetWidget> strongThis(this);
  931. GetCurrentWidgetListener()->WillPaintWindow(this);
  932. if (GetCurrentWidgetListener()) {
  933. #ifdef DEBUG
  934. debug_DumpPaintEvent(stderr, this, region.ToUnknownRegion(),
  935. "PuppetWidget", 0);
  936. #endif
  937. if (mozilla::layers::LayersBackend::LAYERS_CLIENT == mLayerManager->GetBackendType()) {
  938. // Do nothing, the compositor will handle drawing
  939. if (mTabChild) {
  940. mTabChild->NotifyPainted();
  941. }
  942. } else if (mozilla::layers::LayersBackend::LAYERS_BASIC == mLayerManager->GetBackendType()) {
  943. RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(mDrawTarget);
  944. if (!ctx) {
  945. gfxDevCrash(LogReason::InvalidContext) << "PuppetWidget context problem " << gfx::hexa(mDrawTarget);
  946. return NS_ERROR_FAILURE;
  947. }
  948. ctx->Rectangle(gfxRect(0,0,0,0));
  949. ctx->Clip();
  950. AutoLayerManagerSetup setupLayerManager(this, ctx,
  951. BufferMode::BUFFER_NONE);
  952. GetCurrentWidgetListener()->PaintWindow(this, region);
  953. if (mTabChild) {
  954. mTabChild->NotifyPainted();
  955. }
  956. }
  957. }
  958. if (GetCurrentWidgetListener()) {
  959. GetCurrentWidgetListener()->DidPaintWindow();
  960. }
  961. return NS_OK;
  962. }
  963. void
  964. PuppetWidget::SetChild(PuppetWidget* aChild)
  965. {
  966. MOZ_ASSERT(this != aChild, "can't parent a widget to itself");
  967. MOZ_ASSERT(!aChild->mChild,
  968. "fake widget 'hierarchy' only expected to have one level");
  969. mChild = aChild;
  970. }
  971. NS_IMETHODIMP
  972. PuppetWidget::PaintTask::Run()
  973. {
  974. if (mWidget) {
  975. mWidget->Paint();
  976. }
  977. return NS_OK;
  978. }
  979. void
  980. PuppetWidget::PaintNowIfNeeded()
  981. {
  982. if (IsVisible() && mPaintTask.IsPending()) {
  983. Paint();
  984. }
  985. }
  986. NS_IMPL_ISUPPORTS(PuppetWidget::MemoryPressureObserver, nsIObserver)
  987. NS_IMETHODIMP
  988. PuppetWidget::MemoryPressureObserver::Observe(nsISupports* aSubject,
  989. const char* aTopic,
  990. const char16_t* aData)
  991. {
  992. if (!mWidget) {
  993. return NS_OK;
  994. }
  995. if (strcmp("memory-pressure", aTopic) == 0 &&
  996. !NS_LITERAL_STRING("lowering-priority").Equals(aData)) {
  997. if (!mWidget->mVisible && mWidget->mLayerManager &&
  998. XRE_IsContentProcess()) {
  999. mWidget->mLayerManager->ClearCachedResources();
  1000. }
  1001. }
  1002. return NS_OK;
  1003. }
  1004. void
  1005. PuppetWidget::MemoryPressureObserver::Remove()
  1006. {
  1007. nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
  1008. if (obs) {
  1009. obs->RemoveObserver(this, "memory-pressure");
  1010. }
  1011. mWidget = nullptr;
  1012. }
  1013. bool
  1014. PuppetWidget::NeedsPaint()
  1015. {
  1016. // e10s popups are handled by the parent process, so never should be painted here
  1017. if (XRE_IsContentProcess() &&
  1018. Preferences::GetBool("browser.tabs.remote.desktopbehavior", false) &&
  1019. mWindowType == eWindowType_popup) {
  1020. NS_WARNING("Trying to paint an e10s popup in the child process!");
  1021. return false;
  1022. }
  1023. return mVisible;
  1024. }
  1025. float
  1026. PuppetWidget::GetDPI()
  1027. {
  1028. if (mDPI < 0) {
  1029. if (mTabChild) {
  1030. mTabChild->GetDPI(&mDPI);
  1031. } else {
  1032. mDPI = 96.0;
  1033. }
  1034. }
  1035. return mDPI;
  1036. }
  1037. double
  1038. PuppetWidget::GetDefaultScaleInternal()
  1039. {
  1040. if (mDefaultScale < 0) {
  1041. if (mTabChild) {
  1042. mTabChild->GetDefaultScale(&mDefaultScale);
  1043. } else {
  1044. mDefaultScale = 1;
  1045. }
  1046. }
  1047. return mDefaultScale;
  1048. }
  1049. int32_t
  1050. PuppetWidget::RoundsWidgetCoordinatesTo()
  1051. {
  1052. if (mRounding < 0) {
  1053. if (mTabChild) {
  1054. mTabChild->GetWidgetRounding(&mRounding);
  1055. } else {
  1056. mRounding = 1;
  1057. }
  1058. }
  1059. return mRounding;
  1060. }
  1061. void*
  1062. PuppetWidget::GetNativeData(uint32_t aDataType)
  1063. {
  1064. switch (aDataType) {
  1065. case NS_NATIVE_SHAREABLE_WINDOW: {
  1066. MOZ_ASSERT(mTabChild, "Need TabChild to get the nativeWindow from!");
  1067. mozilla::WindowsHandle nativeData = 0;
  1068. if (mTabChild) {
  1069. mTabChild->SendGetWidgetNativeData(&nativeData);
  1070. }
  1071. return (void*)nativeData;
  1072. }
  1073. case NS_NATIVE_WINDOW:
  1074. case NS_NATIVE_WIDGET:
  1075. case NS_NATIVE_DISPLAY:
  1076. // These types are ignored (see bug 1183828, bug 1240891).
  1077. break;
  1078. case NS_RAW_NATIVE_IME_CONTEXT:
  1079. MOZ_CRASH("You need to call GetNativeIMEContext() instead");
  1080. case NS_NATIVE_PLUGIN_PORT:
  1081. case NS_NATIVE_GRAPHIC:
  1082. case NS_NATIVE_SHELLWIDGET:
  1083. default:
  1084. NS_WARNING("nsWindow::GetNativeData called with bad value");
  1085. break;
  1086. }
  1087. return nullptr;
  1088. }
  1089. #if defined(XP_WIN)
  1090. void
  1091. PuppetWidget::SetNativeData(uint32_t aDataType, uintptr_t aVal)
  1092. {
  1093. switch (aDataType) {
  1094. case NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW:
  1095. MOZ_ASSERT(mTabChild, "Need TabChild to send the message.");
  1096. if (mTabChild) {
  1097. mTabChild->SendSetNativeChildOfShareableWindow(aVal);
  1098. }
  1099. break;
  1100. default:
  1101. NS_WARNING("SetNativeData called with unsupported data type.");
  1102. }
  1103. }
  1104. #endif
  1105. nsIntPoint
  1106. PuppetWidget::GetChromeDimensions()
  1107. {
  1108. if (!GetOwningTabChild()) {
  1109. NS_WARNING("PuppetWidget without Tab does not have chrome information.");
  1110. return nsIntPoint();
  1111. }
  1112. return GetOwningTabChild()->GetChromeDisplacement().ToUnknownPoint();
  1113. }
  1114. nsIntPoint
  1115. PuppetWidget::GetWindowPosition()
  1116. {
  1117. if (!GetOwningTabChild()) {
  1118. return nsIntPoint();
  1119. }
  1120. int32_t winX, winY, winW, winH;
  1121. NS_ENSURE_SUCCESS(GetOwningTabChild()->GetDimensions(0, &winX, &winY, &winW, &winH), nsIntPoint());
  1122. return nsIntPoint(winX, winY) + GetOwningTabChild()->GetClientOffset().ToUnknownPoint();
  1123. }
  1124. LayoutDeviceIntRect
  1125. PuppetWidget::GetScreenBounds()
  1126. {
  1127. return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds.Size());
  1128. }
  1129. uint32_t PuppetWidget::GetMaxTouchPoints() const
  1130. {
  1131. static uint32_t sTouchPoints = 0;
  1132. static bool sIsInitialized = false;
  1133. if (sIsInitialized) {
  1134. return sTouchPoints;
  1135. }
  1136. if (mTabChild) {
  1137. mTabChild->GetMaxTouchPoints(&sTouchPoints);
  1138. sIsInitialized = true;
  1139. }
  1140. return sTouchPoints;
  1141. }
  1142. void
  1143. PuppetWidget::StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
  1144. {
  1145. mTabChild->StartScrollbarDrag(aDragMetrics);
  1146. }
  1147. PuppetScreen::PuppetScreen(void *nativeScreen)
  1148. {
  1149. }
  1150. PuppetScreen::~PuppetScreen()
  1151. {
  1152. }
  1153. static ScreenConfiguration
  1154. ScreenConfig()
  1155. {
  1156. ScreenConfiguration config;
  1157. hal::GetCurrentScreenConfiguration(&config);
  1158. return config;
  1159. }
  1160. nsIntSize
  1161. PuppetWidget::GetScreenDimensions()
  1162. {
  1163. nsIntRect r = ScreenConfig().rect();
  1164. return nsIntSize(r.width, r.height);
  1165. }
  1166. NS_IMETHODIMP
  1167. PuppetScreen::GetId(uint32_t *outId)
  1168. {
  1169. *outId = 1;
  1170. return NS_OK;
  1171. }
  1172. NS_IMETHODIMP
  1173. PuppetScreen::GetRect(int32_t *outLeft, int32_t *outTop,
  1174. int32_t *outWidth, int32_t *outHeight)
  1175. {
  1176. nsIntRect r = ScreenConfig().rect();
  1177. *outLeft = r.x;
  1178. *outTop = r.y;
  1179. *outWidth = r.width;
  1180. *outHeight = r.height;
  1181. return NS_OK;
  1182. }
  1183. NS_IMETHODIMP
  1184. PuppetScreen::GetAvailRect(int32_t *outLeft, int32_t *outTop,
  1185. int32_t *outWidth, int32_t *outHeight)
  1186. {
  1187. return GetRect(outLeft, outTop, outWidth, outHeight);
  1188. }
  1189. NS_IMETHODIMP
  1190. PuppetScreen::GetPixelDepth(int32_t *aPixelDepth)
  1191. {
  1192. *aPixelDepth = ScreenConfig().pixelDepth();
  1193. return NS_OK;
  1194. }
  1195. NS_IMETHODIMP
  1196. PuppetScreen::GetColorDepth(int32_t *aColorDepth)
  1197. {
  1198. *aColorDepth = ScreenConfig().colorDepth();
  1199. return NS_OK;
  1200. }
  1201. NS_IMETHODIMP
  1202. PuppetScreen::GetRotation(uint32_t* aRotation)
  1203. {
  1204. NS_WARNING("Attempt to get screen rotation through nsIScreen::GetRotation(). Nothing should know or care this in sandboxed contexts. If you want *orientation*, use hal.");
  1205. return NS_ERROR_NOT_AVAILABLE;
  1206. }
  1207. NS_IMETHODIMP
  1208. PuppetScreen::SetRotation(uint32_t aRotation)
  1209. {
  1210. NS_WARNING("Attempt to set screen rotation through nsIScreen::GetRotation(). Nothing should know or care this in sandboxed contexts. If you want *orientation*, use hal.");
  1211. return NS_ERROR_NOT_AVAILABLE;
  1212. }
  1213. NS_IMPL_ISUPPORTS(PuppetScreenManager, nsIScreenManager)
  1214. PuppetScreenManager::PuppetScreenManager()
  1215. {
  1216. mOneScreen = new PuppetScreen(nullptr);
  1217. }
  1218. PuppetScreenManager::~PuppetScreenManager()
  1219. {
  1220. }
  1221. NS_IMETHODIMP
  1222. PuppetScreenManager::ScreenForId(uint32_t aId,
  1223. nsIScreen** outScreen)
  1224. {
  1225. NS_IF_ADDREF(*outScreen = mOneScreen.get());
  1226. return NS_OK;
  1227. }
  1228. NS_IMETHODIMP
  1229. PuppetScreenManager::GetPrimaryScreen(nsIScreen** outScreen)
  1230. {
  1231. NS_IF_ADDREF(*outScreen = mOneScreen.get());
  1232. return NS_OK;
  1233. }
  1234. NS_IMETHODIMP
  1235. PuppetScreenManager::ScreenForRect(int32_t inLeft,
  1236. int32_t inTop,
  1237. int32_t inWidth,
  1238. int32_t inHeight,
  1239. nsIScreen** outScreen)
  1240. {
  1241. return GetPrimaryScreen(outScreen);
  1242. }
  1243. NS_IMETHODIMP
  1244. PuppetScreenManager::ScreenForNativeWidget(void* aWidget,
  1245. nsIScreen** outScreen)
  1246. {
  1247. return GetPrimaryScreen(outScreen);
  1248. }
  1249. NS_IMETHODIMP
  1250. PuppetScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens)
  1251. {
  1252. *aNumberOfScreens = 1;
  1253. return NS_OK;
  1254. }
  1255. NS_IMETHODIMP
  1256. PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale)
  1257. {
  1258. *aDefaultScale = 1.0f;
  1259. return NS_OK;
  1260. }
  1261. nsIWidgetListener*
  1262. PuppetWidget::GetCurrentWidgetListener()
  1263. {
  1264. if (!mPreviouslyAttachedWidgetListener ||
  1265. !mAttachedWidgetListener) {
  1266. return mAttachedWidgetListener;
  1267. }
  1268. if (mAttachedWidgetListener->GetView()->IsPrimaryFramePaintSuppressed()) {
  1269. return mPreviouslyAttachedWidgetListener;
  1270. }
  1271. return mAttachedWidgetListener;
  1272. }
  1273. void
  1274. PuppetWidget::SetCandidateWindowForPlugin(
  1275. const CandidateWindowPosition& aPosition)
  1276. {
  1277. if (!mTabChild) {
  1278. return;
  1279. }
  1280. mTabChild->SendSetCandidateWindowForPlugin(aPosition);
  1281. }
  1282. void
  1283. PuppetWidget::ZoomToRect(const uint32_t& aPresShellId,
  1284. const FrameMetrics::ViewID& aViewId,
  1285. const CSSRect& aRect,
  1286. const uint32_t& aFlags)
  1287. {
  1288. if (!mTabChild) {
  1289. return;
  1290. }
  1291. mTabChild->ZoomToRect(aPresShellId, aViewId, aRect, aFlags);
  1292. }
  1293. void
  1294. PuppetWidget::LookUpDictionary(
  1295. const nsAString& aText,
  1296. const nsTArray<mozilla::FontRange>& aFontRangeArray,
  1297. const bool aIsVertical,
  1298. const LayoutDeviceIntPoint& aPoint)
  1299. {
  1300. if (!mTabChild) {
  1301. return;
  1302. }
  1303. mTabChild->SendLookUpDictionary(nsString(aText), aFontRangeArray, aIsVertical, aPoint);
  1304. }
  1305. bool
  1306. PuppetWidget::HasPendingInputEvent()
  1307. {
  1308. if (!mTabChild) {
  1309. return false;
  1310. }
  1311. bool ret = false;
  1312. mTabChild->GetIPCChannel()->PeekMessages(
  1313. [&ret](const IPC::Message& aMsg) -> bool {
  1314. if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart)
  1315. == mozilla::dom::PBrowser::PBrowserStart) {
  1316. switch (aMsg.type()) {
  1317. case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
  1318. case mozilla::dom::PBrowser::Msg_SynthMouseMoveEvent__ID:
  1319. case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
  1320. case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
  1321. case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
  1322. case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
  1323. case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
  1324. case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
  1325. case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
  1326. case mozilla::dom::PBrowser::Msg_MouseEvent__ID:
  1327. case mozilla::dom::PBrowser::Msg_KeyEvent__ID:
  1328. ret = true;
  1329. return false; // Stop peeking.
  1330. }
  1331. }
  1332. return true;
  1333. }
  1334. );
  1335. return ret;
  1336. }
  1337. void
  1338. PuppetWidget::HandledWindowedPluginKeyEvent(
  1339. const NativeEventData& aKeyEventData,
  1340. bool aIsConsumed)
  1341. {
  1342. if (NS_WARN_IF(mKeyEventInPluginCallbacks.IsEmpty())) {
  1343. return;
  1344. }
  1345. nsCOMPtr<nsIKeyEventInPluginCallback> callback =
  1346. mKeyEventInPluginCallbacks[0];
  1347. MOZ_ASSERT(callback);
  1348. mKeyEventInPluginCallbacks.RemoveElementAt(0);
  1349. callback->HandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
  1350. }
  1351. nsresult
  1352. PuppetWidget::OnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
  1353. nsIKeyEventInPluginCallback* aCallback)
  1354. {
  1355. if (NS_WARN_IF(!mTabChild)) {
  1356. return NS_ERROR_NOT_AVAILABLE;
  1357. }
  1358. if (NS_WARN_IF(!mTabChild->SendOnWindowedPluginKeyEvent(aKeyEventData))) {
  1359. return NS_ERROR_FAILURE;
  1360. }
  1361. mKeyEventInPluginCallbacks.AppendElement(aCallback);
  1362. return NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY;
  1363. }
  1364. } // namespace widget
  1365. } // namespace mozilla