LCOV - code coverage report
Current view: top level - widget - PuppetWidget.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 148 654 22.6 %
Date: 2017-07-14 16:53:18 Functions: 26 100 26.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13