forked from mirrors/gecko-dev
		
	This patch removes the return value, because none of the call sites check it. --HG-- extra : rebase_source : c308e7edd03e9ba6d2f0c8f032438bc7743baa1f
		
			
				
	
	
		
			1528 lines
		
	
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1528 lines
		
	
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 | 
						|
 * vim: sw=2 ts=8 et :
 | 
						|
 */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#include "base/basictypes.h"
 | 
						|
 | 
						|
#include "ClientLayerManager.h"
 | 
						|
#include "gfxPlatform.h"
 | 
						|
#include "mozilla/dom/TabChild.h"
 | 
						|
#include "mozilla/Hal.h"
 | 
						|
#include "mozilla/IMEStateManager.h"
 | 
						|
#include "mozilla/layers/APZChild.h"
 | 
						|
#include "mozilla/layers/PLayerTransactionChild.h"
 | 
						|
#include "mozilla/Preferences.h"
 | 
						|
#include "mozilla/TextComposition.h"
 | 
						|
#include "mozilla/TextEvents.h"
 | 
						|
#include "mozilla/Unused.h"
 | 
						|
#include "PuppetWidget.h"
 | 
						|
#include "nsContentUtils.h"
 | 
						|
#include "nsIWidgetListener.h"
 | 
						|
#include "imgIContainer.h"
 | 
						|
#include "nsView.h"
 | 
						|
 | 
						|
using namespace mozilla;
 | 
						|
using namespace mozilla::dom;
 | 
						|
using namespace mozilla::hal;
 | 
						|
using namespace mozilla::gfx;
 | 
						|
using namespace mozilla::layers;
 | 
						|
using namespace mozilla::widget;
 | 
						|
 | 
						|
static void
 | 
						|
InvalidateRegion(nsIWidget* aWidget, const LayoutDeviceIntRegion& aRegion)
 | 
						|
{
 | 
						|
  for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) {
 | 
						|
    aWidget->Invalidate(iter.Get());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/*static*/ already_AddRefed<nsIWidget>
 | 
						|
nsIWidget::CreatePuppetWidget(TabChild* aTabChild)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(!aTabChild || nsIWidget::UsePuppetWidgets(),
 | 
						|
             "PuppetWidgets not allowed in this configuration");
 | 
						|
 | 
						|
  nsCOMPtr<nsIWidget> widget = new PuppetWidget(aTabChild);
 | 
						|
  return widget.forget();
 | 
						|
}
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace widget {
 | 
						|
 | 
						|
static bool
 | 
						|
IsPopup(const nsWidgetInitData* aInitData)
 | 
						|
{
 | 
						|
  return aInitData && aInitData->mWindowType == eWindowType_popup;
 | 
						|
}
 | 
						|
 | 
						|
static bool
 | 
						|
MightNeedIMEFocus(const nsWidgetInitData* aInitData)
 | 
						|
{
 | 
						|
  // In the puppet-widget world, popup widgets are just dummies and
 | 
						|
  // shouldn't try to mess with IME state.
 | 
						|
#ifdef MOZ_CROSS_PROCESS_IME
 | 
						|
  return !IsPopup(aInitData);
 | 
						|
#else
 | 
						|
  return false;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
// Arbitrary, fungible.
 | 
						|
const size_t PuppetWidget::kMaxDimension = 4000;
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS_INHERITED0(PuppetWidget, nsBaseWidget)
 | 
						|
 | 
						|
PuppetWidget::PuppetWidget(TabChild* aTabChild)
 | 
						|
  : mTabChild(aTabChild)
 | 
						|
  , mMemoryPressureObserver(nullptr)
 | 
						|
  , mDPI(-1)
 | 
						|
  , mDefaultScale(-1)
 | 
						|
  , mCursorHotspotX(0)
 | 
						|
  , mCursorHotspotY(0)
 | 
						|
  , mNativeKeyCommandsValid(false)
 | 
						|
{
 | 
						|
  MOZ_COUNT_CTOR(PuppetWidget);
 | 
						|
 | 
						|
  mSingleLineCommands.SetCapacity(4);
 | 
						|
  mMultiLineCommands.SetCapacity(4);
 | 
						|
  mRichTextCommands.SetCapacity(4);
 | 
						|
 | 
						|
  // Setting 'Unknown' means "not yet cached".
 | 
						|
  mInputContext.mIMEState.mEnabled = IMEState::UNKNOWN;
 | 
						|
}
 | 
						|
 | 
						|
PuppetWidget::~PuppetWidget()
 | 
						|
{
 | 
						|
  MOZ_COUNT_DTOR(PuppetWidget);
 | 
						|
 | 
						|
  Destroy();
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::InfallibleCreate(nsIWidget* aParent,
 | 
						|
                               nsNativeWidget aNativeParent,
 | 
						|
                               const LayoutDeviceIntRect& aRect,
 | 
						|
                               nsWidgetInitData* aInitData)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(!aNativeParent, "got a non-Puppet native parent");
 | 
						|
 | 
						|
  BaseCreate(nullptr, aInitData);
 | 
						|
 | 
						|
  mBounds = aRect;
 | 
						|
  mEnabled = true;
 | 
						|
  mVisible = true;
 | 
						|
 | 
						|
  mDrawTarget = gfxPlatform::GetPlatform()->
 | 
						|
    CreateOffscreenContentDrawTarget(IntSize(1, 1), SurfaceFormat::B8G8R8A8);
 | 
						|
 | 
						|
  mNeedIMEStateInit = MightNeedIMEFocus(aInitData);
 | 
						|
 | 
						|
  PuppetWidget* parent = static_cast<PuppetWidget*>(aParent);
 | 
						|
  if (parent) {
 | 
						|
    parent->SetChild(this);
 | 
						|
    mLayerManager = parent->GetLayerManager();
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    Resize(mBounds.x, mBounds.y, mBounds.width, mBounds.height, false);
 | 
						|
  }
 | 
						|
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
 | 
						|
  if (obs) {
 | 
						|
    mMemoryPressureObserver = new MemoryPressureObserver(this);
 | 
						|
    obs->AddObserver(mMemoryPressureObserver, "memory-pressure", false);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::Create(nsIWidget* aParent,
 | 
						|
                     nsNativeWidget aNativeParent,
 | 
						|
                     const LayoutDeviceIntRect& aRect,
 | 
						|
                     nsWidgetInitData* aInitData)
 | 
						|
{
 | 
						|
  InfallibleCreate(aParent, aNativeParent, aRect, aInitData);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::InitIMEState()
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mTabChild);
 | 
						|
  if (mNeedIMEStateInit) {
 | 
						|
    mContentCache.Clear();
 | 
						|
    mTabChild->SendUpdateContentCache(mContentCache);
 | 
						|
    mIMEPreferenceOfParent = nsIMEUpdatePreference();
 | 
						|
    mNeedIMEStateInit = false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
already_AddRefed<nsIWidget>
 | 
						|
PuppetWidget::CreateChild(const LayoutDeviceIntRect& aRect,
 | 
						|
                          nsWidgetInitData* aInitData,
 | 
						|
                          bool aForceUseIWidgetParent)
 | 
						|
{
 | 
						|
  bool isPopup = IsPopup(aInitData);
 | 
						|
  nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(mTabChild);
 | 
						|
  return ((widget &&
 | 
						|
           NS_SUCCEEDED(widget->Create(isPopup ? nullptr: this, nullptr, aRect,
 | 
						|
                                       aInitData))) ?
 | 
						|
          widget.forget() : nullptr);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::Destroy()
 | 
						|
{
 | 
						|
  if (mOnDestroyCalled) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  mOnDestroyCalled = true;
 | 
						|
 | 
						|
  Base::OnDestroy();
 | 
						|
  Base::Destroy();
 | 
						|
  mPaintTask.Revoke();
 | 
						|
  if (mMemoryPressureObserver) {
 | 
						|
    mMemoryPressureObserver->Remove();
 | 
						|
  }
 | 
						|
  mMemoryPressureObserver = nullptr;
 | 
						|
  mChild = nullptr;
 | 
						|
  if (mLayerManager) {
 | 
						|
    mLayerManager->Destroy();
 | 
						|
  }
 | 
						|
  mLayerManager = nullptr;
 | 
						|
  mTabChild = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::Show(bool aState)
 | 
						|
{
 | 
						|
  NS_ASSERTION(mEnabled,
 | 
						|
               "does it make sense to Show()/Hide() a disabled widget?");
 | 
						|
 | 
						|
  bool wasVisible = mVisible;
 | 
						|
  mVisible = aState;
 | 
						|
 | 
						|
  if (mChild) {
 | 
						|
    mChild->mVisible = aState;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!wasVisible && mVisible) {
 | 
						|
    Resize(mBounds.width, mBounds.height, false);
 | 
						|
    Invalidate(mBounds);
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::Resize(double aWidth,
 | 
						|
                     double aHeight,
 | 
						|
                     bool   aRepaint)
 | 
						|
{
 | 
						|
  LayoutDeviceIntRect oldBounds = mBounds;
 | 
						|
  mBounds.SizeTo(LayoutDeviceIntSize(NSToIntRound(aWidth),
 | 
						|
                                     NSToIntRound(aHeight)));
 | 
						|
 | 
						|
  if (mChild) {
 | 
						|
    return mChild->Resize(aWidth, aHeight, aRepaint);
 | 
						|
  }
 | 
						|
 | 
						|
  // XXX: roc says that |aRepaint| dictates whether or not to
 | 
						|
  // invalidate the expanded area
 | 
						|
  if (oldBounds.Size() < mBounds.Size() && aRepaint) {
 | 
						|
    LayoutDeviceIntRegion dirty(mBounds);
 | 
						|
    dirty.Sub(dirty, oldBounds);
 | 
						|
    InvalidateRegion(this, dirty);
 | 
						|
  }
 | 
						|
 | 
						|
  // call WindowResized() on both the current listener, and possibly
 | 
						|
  // also the previous one if we're in a state where we're drawing that one
 | 
						|
  // because the current one is paint suppressed
 | 
						|
  if (!oldBounds.IsEqualEdges(mBounds) && mAttachedWidgetListener) {
 | 
						|
    if (GetCurrentWidgetListener() &&
 | 
						|
        GetCurrentWidgetListener() != mAttachedWidgetListener) {
 | 
						|
      GetCurrentWidgetListener()->WindowResized(this, mBounds.width, mBounds.height);
 | 
						|
    }
 | 
						|
    mAttachedWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
 | 
						|
{
 | 
						|
  for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
 | 
						|
    const Configuration& configuration = aConfigurations[i];
 | 
						|
    PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild.get());
 | 
						|
    NS_ASSERTION(w->GetParent() == this,
 | 
						|
                 "Configured widget is not a child");
 | 
						|
    w->SetWindowClipRegion(configuration.mClipRegion, true);
 | 
						|
    LayoutDeviceIntRect bounds = w->GetBounds();
 | 
						|
    if (bounds.Size() != configuration.mBounds.Size()) {
 | 
						|
      w->Resize(configuration.mBounds.x, configuration.mBounds.y,
 | 
						|
                configuration.mBounds.width, configuration.mBounds.height,
 | 
						|
                true);
 | 
						|
    } else if (bounds.TopLeft() != configuration.mBounds.TopLeft()) {
 | 
						|
      w->Move(configuration.mBounds.x, configuration.mBounds.y);
 | 
						|
    }
 | 
						|
    w->SetWindowClipRegion(configuration.mClipRegion, false);
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::SetFocus(bool aRaise)
 | 
						|
{
 | 
						|
  if (aRaise && mTabChild) {
 | 
						|
    mTabChild->SendRequestFocus(true);
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::Invalidate(const LayoutDeviceIntRect& aRect)
 | 
						|
{
 | 
						|
#ifdef DEBUG
 | 
						|
  debug_DumpInvalidate(stderr, this, &aRect, "PuppetWidget", 0);
 | 
						|
#endif
 | 
						|
 | 
						|
  if (mChild) {
 | 
						|
    return mChild->Invalidate(aRect);
 | 
						|
  }
 | 
						|
 | 
						|
  mDirtyRegion.Or(mDirtyRegion, aRect);
 | 
						|
 | 
						|
  if (!mDirtyRegion.IsEmpty() && !mPaintTask.IsPending()) {
 | 
						|
    mPaintTask = new PaintTask(this);
 | 
						|
    return NS_DispatchToCurrentThread(mPaintTask.get());
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::InitEvent(WidgetGUIEvent& event, LayoutDeviceIntPoint* aPoint)
 | 
						|
{
 | 
						|
  if (nullptr == aPoint) {
 | 
						|
    event.mRefPoint = LayoutDeviceIntPoint(0, 0);
 | 
						|
  } else {
 | 
						|
    // use the point override if provided
 | 
						|
    event.mRefPoint = *aPoint;
 | 
						|
  }
 | 
						|
  event.mTime = PR_Now() / 1000;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
 | 
						|
{
 | 
						|
#ifdef DEBUG
 | 
						|
  debug_DumpEvent(stdout, event->mWidget, event, "PuppetWidget", 0);
 | 
						|
#endif
 | 
						|
 | 
						|
  MOZ_ASSERT(!mChild || mChild->mWindowType == eWindowType_popup,
 | 
						|
             "Unexpected event dispatch!");
 | 
						|
 | 
						|
  AutoCacheNativeKeyCommands autoCache(this);
 | 
						|
  if (event->mFlags.mIsSynthesizedForTests && !mNativeKeyCommandsValid) {
 | 
						|
    WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
 | 
						|
    if (keyEvent) {
 | 
						|
      mTabChild->RequestNativeKeyBindings(&autoCache, keyEvent);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (event->mClass == eCompositionEventClass) {
 | 
						|
    // Store the latest native IME context of parent process's widget or
 | 
						|
    // TextEventDispatcher if it's in this process.
 | 
						|
    WidgetCompositionEvent* compositionEvent = event->AsCompositionEvent();
 | 
						|
#ifdef DEBUG
 | 
						|
    if (mNativeIMEContext.IsValid() &&
 | 
						|
        mNativeIMEContext != compositionEvent->mNativeIMEContext) {
 | 
						|
      RefPtr<TextComposition> composition =
 | 
						|
        IMEStateManager::GetTextCompositionFor(this);
 | 
						|
      MOZ_ASSERT(!composition,
 | 
						|
        "When there is composition caused by old native IME context, "
 | 
						|
        "composition events caused by different native IME context are not "
 | 
						|
        "allowed");
 | 
						|
    }
 | 
						|
#endif // #ifdef DEBUG
 | 
						|
    mNativeIMEContext = compositionEvent->mNativeIMEContext;
 | 
						|
  }
 | 
						|
 | 
						|
  aStatus = nsEventStatus_eIgnore;
 | 
						|
 | 
						|
  if (GetCurrentWidgetListener()) {
 | 
						|
    aStatus = GetCurrentWidgetListener()->HandleEvent(event, mUseAttachedEvents);
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsEventStatus
 | 
						|
PuppetWidget::DispatchInputEvent(WidgetInputEvent* aEvent)
 | 
						|
{
 | 
						|
  if (!AsyncPanZoomEnabled()) {
 | 
						|
    nsEventStatus status = nsEventStatus_eIgnore;
 | 
						|
    DispatchEvent(aEvent, status);
 | 
						|
    return status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mTabChild) {
 | 
						|
    return nsEventStatus_eIgnore;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (aEvent->mClass) {
 | 
						|
    case eWheelEventClass:
 | 
						|
      Unused <<
 | 
						|
        mTabChild->SendDispatchWheelEvent(*aEvent->AsWheelEvent());
 | 
						|
      break;
 | 
						|
    case eMouseEventClass:
 | 
						|
      Unused <<
 | 
						|
        mTabChild->SendDispatchMouseEvent(*aEvent->AsMouseEvent());
 | 
						|
      break;
 | 
						|
    case eKeyboardEventClass:
 | 
						|
      Unused <<
 | 
						|
        mTabChild->SendDispatchKeyboardEvent(*aEvent->AsKeyboardEvent());
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      MOZ_ASSERT_UNREACHABLE("unsupported event type");
 | 
						|
  }
 | 
						|
 | 
						|
  return nsEventStatus_eIgnore;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout,
 | 
						|
                                       int32_t aNativeKeyCode,
 | 
						|
                                       uint32_t aModifierFlags,
 | 
						|
                                       const nsAString& aCharacters,
 | 
						|
                                       const nsAString& aUnmodifiedCharacters,
 | 
						|
                                       nsIObserver* aObserver)
 | 
						|
{
 | 
						|
  AutoObserverNotifier notifier(aObserver, "keyevent");
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendSynthesizeNativeKeyEvent(aNativeKeyboardLayout, aNativeKeyCode,
 | 
						|
    aModifierFlags, nsString(aCharacters), nsString(aUnmodifiedCharacters),
 | 
						|
    notifier.SaveObserver());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::SynthesizeNativeMouseEvent(mozilla::LayoutDeviceIntPoint aPoint,
 | 
						|
                                         uint32_t aNativeMessage,
 | 
						|
                                         uint32_t aModifierFlags,
 | 
						|
                                         nsIObserver* aObserver)
 | 
						|
{
 | 
						|
  AutoObserverNotifier notifier(aObserver, "mouseevent");
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendSynthesizeNativeMouseEvent(aPoint, aNativeMessage,
 | 
						|
    aModifierFlags, notifier.SaveObserver());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::SynthesizeNativeMouseMove(mozilla::LayoutDeviceIntPoint aPoint,
 | 
						|
                                        nsIObserver* aObserver)
 | 
						|
{
 | 
						|
  AutoObserverNotifier notifier(aObserver, "mousemove");
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendSynthesizeNativeMouseMove(aPoint, notifier.SaveObserver());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::SynthesizeNativeMouseScrollEvent(mozilla::LayoutDeviceIntPoint aPoint,
 | 
						|
                                               uint32_t aNativeMessage,
 | 
						|
                                               double aDeltaX,
 | 
						|
                                               double aDeltaY,
 | 
						|
                                               double aDeltaZ,
 | 
						|
                                               uint32_t aModifierFlags,
 | 
						|
                                               uint32_t aAdditionalFlags,
 | 
						|
                                               nsIObserver* aObserver)
 | 
						|
{
 | 
						|
  AutoObserverNotifier notifier(aObserver, "mousescrollevent");
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendSynthesizeNativeMouseScrollEvent(aPoint, aNativeMessage,
 | 
						|
    aDeltaX, aDeltaY, aDeltaZ, aModifierFlags, aAdditionalFlags,
 | 
						|
    notifier.SaveObserver());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::SynthesizeNativeTouchPoint(uint32_t aPointerId,
 | 
						|
                                         TouchPointerState aPointerState,
 | 
						|
                                         LayoutDeviceIntPoint aPoint,
 | 
						|
                                         double aPointerPressure,
 | 
						|
                                         uint32_t aPointerOrientation,
 | 
						|
                                         nsIObserver* aObserver)
 | 
						|
{
 | 
						|
  AutoObserverNotifier notifier(aObserver, "touchpoint");
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendSynthesizeNativeTouchPoint(aPointerId, aPointerState,
 | 
						|
    aPoint, aPointerPressure, aPointerOrientation,
 | 
						|
    notifier.SaveObserver());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint,
 | 
						|
                                       bool aLongTap,
 | 
						|
                                       nsIObserver* aObserver)
 | 
						|
{
 | 
						|
  AutoObserverNotifier notifier(aObserver, "touchtap");
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendSynthesizeNativeTouchTap(aPoint, aLongTap,
 | 
						|
    notifier.SaveObserver());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::ClearNativeTouchSequence(nsIObserver* aObserver)
 | 
						|
{
 | 
						|
  AutoObserverNotifier notifier(aObserver, "cleartouch");
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendClearNativeTouchSequence(notifier.SaveObserver());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 
 | 
						|
void
 | 
						|
PuppetWidget::SetConfirmedTargetAPZC(uint64_t aInputBlockId,
 | 
						|
                                     const nsTArray<ScrollableLayerGuid>& aTargets) const
 | 
						|
{
 | 
						|
  if (mTabChild) {
 | 
						|
    mTabChild->SetTargetAPZC(aInputBlockId, aTargets);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::UpdateZoomConstraints(const uint32_t& aPresShellId,
 | 
						|
                                    const FrameMetrics::ViewID& aViewId,
 | 
						|
                                    const Maybe<ZoomConstraints>& aConstraints)
 | 
						|
{
 | 
						|
  if (mTabChild) {
 | 
						|
    mTabChild->DoUpdateZoomConstraints(aPresShellId, aViewId, aConstraints);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
PuppetWidget::AsyncPanZoomEnabled() const
 | 
						|
{
 | 
						|
  return mTabChild && mTabChild->AsyncPanZoomEnabled();
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP_(bool)
 | 
						|
PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
 | 
						|
                                      const mozilla::WidgetKeyboardEvent& aEvent,
 | 
						|
                                      DoCommandCallback aCallback,
 | 
						|
                                      void* aCallbackData)
 | 
						|
{
 | 
						|
  // B2G doesn't have native key bindings.
 | 
						|
#ifdef MOZ_WIDGET_GONK
 | 
						|
  return false;
 | 
						|
#else // #ifdef MOZ_WIDGET_GONK
 | 
						|
  MOZ_ASSERT(mNativeKeyCommandsValid);
 | 
						|
 | 
						|
  const nsTArray<mozilla::CommandInt>* commands = nullptr;
 | 
						|
  switch (aType) {
 | 
						|
    case nsIWidget::NativeKeyBindingsForSingleLineEditor:
 | 
						|
      commands = &mSingleLineCommands;
 | 
						|
      break;
 | 
						|
    case nsIWidget::NativeKeyBindingsForMultiLineEditor:
 | 
						|
      commands = &mMultiLineCommands;
 | 
						|
      break;
 | 
						|
    case nsIWidget::NativeKeyBindingsForRichTextEditor:
 | 
						|
      commands = &mRichTextCommands;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      MOZ_CRASH("Invalid type");
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  if (commands->IsEmpty()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  for (uint32_t i = 0; i < commands->Length(); i++) {
 | 
						|
    aCallback(static_cast<mozilla::Command>((*commands)[i]), aCallbackData);
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
LayerManager*
 | 
						|
PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
 | 
						|
                              LayersBackend aBackendHint,
 | 
						|
                              LayerManagerPersistence aPersistence)
 | 
						|
{
 | 
						|
  if (!mLayerManager) {
 | 
						|
    mLayerManager = new ClientLayerManager(this);
 | 
						|
  }
 | 
						|
  ShadowLayerForwarder* lf = mLayerManager->AsShadowForwarder();
 | 
						|
  if (!lf->HasShadowManager() && aShadowManager) {
 | 
						|
    lf->SetShadowManager(aShadowManager);
 | 
						|
  }
 | 
						|
  return mLayerManager;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::RequestIMEToCommitComposition(bool aCancel)
 | 
						|
{
 | 
						|
#ifdef MOZ_CROSS_PROCESS_IME
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  MOZ_ASSERT(!Destroyed());
 | 
						|
 | 
						|
  // There must not be composition which is caused by the PuppetWidget instance.
 | 
						|
  if (NS_WARN_IF(!mNativeIMEContext.IsValid())) {
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
 | 
						|
  RefPtr<TextComposition> composition =
 | 
						|
    IMEStateManager::GetTextCompositionFor(this);
 | 
						|
  // This method shouldn't be called when there is no text composition instance.
 | 
						|
  if (NS_WARN_IF(!composition)) {
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
 | 
						|
  bool isCommitted = false;
 | 
						|
  nsAutoString committedString;
 | 
						|
  if (NS_WARN_IF(!mTabChild->SendRequestIMEToCommitComposition(
 | 
						|
                               aCancel, &isCommitted, &committedString))) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  // If the composition wasn't committed synchronously, we need to wait async
 | 
						|
  // composition events for destroying the TextComposition instance.
 | 
						|
  if (!isCommitted) {
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
 | 
						|
  // Dispatch eCompositionCommit event.
 | 
						|
  WidgetCompositionEvent compositionCommitEvent(true, eCompositionCommit, this);
 | 
						|
  InitEvent(compositionCommitEvent, nullptr);
 | 
						|
  compositionCommitEvent.mData = committedString;
 | 
						|
  nsEventStatus status = nsEventStatus_eIgnore;
 | 
						|
  DispatchEvent(&compositionCommitEvent, status);
 | 
						|
 | 
						|
  // NOTE: PuppetWidget might be destroyed already.
 | 
						|
 | 
						|
#endif // #ifdef MOZ_CROSS_PROCESS_IME
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::NotifyIMEInternal(const IMENotification& aIMENotification)
 | 
						|
{
 | 
						|
  switch (aIMENotification.mMessage) {
 | 
						|
    case REQUEST_TO_COMMIT_COMPOSITION:
 | 
						|
      return RequestIMEToCommitComposition(false);
 | 
						|
    case REQUEST_TO_CANCEL_COMPOSITION:
 | 
						|
      return RequestIMEToCommitComposition(true);
 | 
						|
    case NOTIFY_IME_OF_FOCUS:
 | 
						|
    case NOTIFY_IME_OF_BLUR:
 | 
						|
      return NotifyIMEOfFocusChange(aIMENotification);
 | 
						|
    case NOTIFY_IME_OF_SELECTION_CHANGE:
 | 
						|
      return NotifyIMEOfSelectionChange(aIMENotification);
 | 
						|
    case NOTIFY_IME_OF_TEXT_CHANGE:
 | 
						|
      return NotifyIMEOfTextChange(aIMENotification);
 | 
						|
    case NOTIFY_IME_OF_COMPOSITION_EVENT_HANDLED:
 | 
						|
      return NotifyIMEOfCompositionUpdate(aIMENotification);
 | 
						|
    case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
 | 
						|
      return NotifyIMEOfMouseButtonEvent(aIMENotification);
 | 
						|
    case NOTIFY_IME_OF_POSITION_CHANGE:
 | 
						|
      return NotifyIMEOfPositionChange(aIMENotification);
 | 
						|
    default:
 | 
						|
      return NS_ERROR_NOT_IMPLEMENTED;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::StartPluginIME(const mozilla::WidgetKeyboardEvent& aKeyboardEvent,
 | 
						|
                             int32_t aPanelX, int32_t aPanelY,
 | 
						|
                             nsString& aCommitted)
 | 
						|
{
 | 
						|
  if (!mTabChild ||
 | 
						|
      !mTabChild->SendStartPluginIME(aKeyboardEvent, aPanelX,
 | 
						|
                                     aPanelY, &aCommitted)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::SetPluginFocused(bool& aFocused)
 | 
						|
{
 | 
						|
  if (mTabChild) {
 | 
						|
    mTabChild->SendSetPluginFocused(aFocused);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::DefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent)
 | 
						|
{
 | 
						|
  if (!mTabChild) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  mTabChild->SendDefaultProcOfPluginEvent(aEvent);
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP_(void)
 | 
						|
PuppetWidget::SetInputContext(const InputContext& aContext,
 | 
						|
                              const InputContextAction& aAction)
 | 
						|
{
 | 
						|
  mInputContext = aContext;
 | 
						|
  // Any widget instances cannot cache IME open state because IME open state
 | 
						|
  // can be changed by user but native IME may not notify us of changing the
 | 
						|
  // open state on some platforms.
 | 
						|
  mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
 | 
						|
 | 
						|
#ifndef MOZ_CROSS_PROCESS_IME
 | 
						|
  return;
 | 
						|
#endif
 | 
						|
 | 
						|
  if (!mTabChild) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  mTabChild->SendSetInputContext(
 | 
						|
    static_cast<int32_t>(aContext.mIMEState.mEnabled),
 | 
						|
    static_cast<int32_t>(aContext.mIMEState.mOpen),
 | 
						|
    aContext.mHTMLInputType,
 | 
						|
    aContext.mHTMLInputInputmode,
 | 
						|
    aContext.mActionHint,
 | 
						|
    static_cast<int32_t>(aAction.mCause),
 | 
						|
    static_cast<int32_t>(aAction.mFocusChange));
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP_(InputContext)
 | 
						|
PuppetWidget::GetInputContext()
 | 
						|
{
 | 
						|
#ifndef MOZ_CROSS_PROCESS_IME
 | 
						|
  return InputContext();
 | 
						|
#endif
 | 
						|
 | 
						|
  // XXX Currently, we don't support retrieving IME open state from child
 | 
						|
  //     process.
 | 
						|
 | 
						|
  // When this widget caches input context and currently managed by
 | 
						|
  // IMEStateManager, the cache is valid.  Only in this case, we can
 | 
						|
  // avoid to use synchronous IPC.
 | 
						|
  if (mInputContext.mIMEState.mEnabled != IMEState::UNKNOWN &&
 | 
						|
      IMEStateManager::GetWidgetForActiveInputContext() == this) {
 | 
						|
    return mInputContext;
 | 
						|
  }
 | 
						|
 | 
						|
  NS_WARNING("PuppetWidget::GetInputContext() needs to retrieve it with IPC");
 | 
						|
 | 
						|
  // Don't cache InputContext here because this process isn't managing IME
 | 
						|
  // state of the chrome widget.  So, we cannot modify mInputContext when
 | 
						|
  // chrome widget is set to new context.
 | 
						|
  InputContext context;
 | 
						|
  if (mTabChild) {
 | 
						|
    int32_t enabled, open;
 | 
						|
    mTabChild->SendGetInputContext(&enabled, &open);
 | 
						|
    context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(enabled);
 | 
						|
    context.mIMEState.mOpen = static_cast<IMEState::Open>(open);
 | 
						|
  }
 | 
						|
  return context;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP_(NativeIMEContext)
 | 
						|
PuppetWidget::GetNativeIMEContext()
 | 
						|
{
 | 
						|
  return mNativeIMEContext;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::NotifyIMEOfFocusChange(const IMENotification& aIMENotification)
 | 
						|
{
 | 
						|
#ifndef MOZ_CROSS_PROCESS_IME
 | 
						|
  return NS_OK;
 | 
						|
#endif
 | 
						|
 | 
						|
  if (!mTabChild)
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  bool gotFocus = aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS;
 | 
						|
  if (gotFocus) {
 | 
						|
    if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN) {
 | 
						|
      // When IME gets focus, we should initalize all information of the
 | 
						|
      // content.
 | 
						|
      if (NS_WARN_IF(!mContentCache.CacheAll(this, &aIMENotification))) {
 | 
						|
        return NS_ERROR_FAILURE;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      // However, if a plugin has focus, only the editor rect information is
 | 
						|
      // available.
 | 
						|
      if (NS_WARN_IF(!mContentCache.CacheEditorRect(this, &aIMENotification))) {
 | 
						|
        return NS_ERROR_FAILURE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // When IME loses focus, we don't need to store anything.
 | 
						|
    mContentCache.Clear();
 | 
						|
  }
 | 
						|
 | 
						|
  mIMEPreferenceOfParent = nsIMEUpdatePreference();
 | 
						|
  if (!mTabChild->SendNotifyIMEFocus(mContentCache, aIMENotification,
 | 
						|
                                     &mIMEPreferenceOfParent)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::NotifyIMEOfCompositionUpdate(
 | 
						|
                const IMENotification& aIMENotification)
 | 
						|
{
 | 
						|
#ifndef MOZ_CROSS_PROCESS_IME
 | 
						|
  return NS_OK;
 | 
						|
#endif
 | 
						|
 | 
						|
  NS_ENSURE_TRUE(mTabChild, NS_ERROR_FAILURE);
 | 
						|
 | 
						|
  if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
 | 
						|
      NS_WARN_IF(!mContentCache.CacheSelection(this, &aIMENotification))) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mTabChild->SendNotifyIMECompositionUpdate(mContentCache, aIMENotification);
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsIMEUpdatePreference
 | 
						|
PuppetWidget::GetIMEUpdatePreference()
 | 
						|
{
 | 
						|
#ifdef MOZ_CROSS_PROCESS_IME
 | 
						|
  // e10s requires IME content cache in in the TabParent for handling query
 | 
						|
  // content event only with the parent process.  Therefore, this process
 | 
						|
  // needs to receive a lot of information from the focused editor to sent
 | 
						|
  // the latest content to the parent process.
 | 
						|
  if (mInputContext.mIMEState.mEnabled == IMEState::PLUGIN) {
 | 
						|
    // But if a plugin has focus, we cannot receive text nor selection change
 | 
						|
    // in the plugin.  Therefore, PuppetWidget needs to receive only position
 | 
						|
    // change event for updating the editor rect cache.
 | 
						|
    return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
 | 
						|
                                 nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE);
 | 
						|
  }
 | 
						|
  return nsIMEUpdatePreference(mIMEPreferenceOfParent.mWantUpdates |
 | 
						|
                               nsIMEUpdatePreference::NOTIFY_TEXT_CHANGE |
 | 
						|
                               nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE );
 | 
						|
#else
 | 
						|
  // B2G doesn't handle IME as widget-level.
 | 
						|
  return nsIMEUpdatePreference();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::NotifyIMEOfTextChange(const IMENotification& aIMENotification)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_TEXT_CHANGE,
 | 
						|
             "Passed wrong notification");
 | 
						|
 | 
						|
#ifndef MOZ_CROSS_PROCESS_IME
 | 
						|
  return NS_OK;
 | 
						|
#endif
 | 
						|
 | 
						|
  if (!mTabChild)
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  // While a plugin has focus, text change notification shouldn't be available.
 | 
						|
  if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  // FYI: text change notification is the first notification after
 | 
						|
  //      a user operation changes the content.  So, we need to modify
 | 
						|
  //      the cache as far as possible here.
 | 
						|
 | 
						|
  if (NS_WARN_IF(!mContentCache.CacheText(this, &aIMENotification))) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  // TabParent doesn't this this to cache.  we don't send the notification
 | 
						|
  // if parent process doesn't request NOTIFY_TEXT_CHANGE.
 | 
						|
  if (mIMEPreferenceOfParent.WantTextChange()) {
 | 
						|
    mTabChild->SendNotifyIMETextChange(mContentCache, aIMENotification);
 | 
						|
  } else {
 | 
						|
    mTabChild->SendUpdateContentCache(mContentCache);
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::NotifyIMEOfSelectionChange(
 | 
						|
                const IMENotification& aIMENotification)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE,
 | 
						|
             "Passed wrong notification");
 | 
						|
 | 
						|
#ifndef MOZ_CROSS_PROCESS_IME
 | 
						|
  return NS_OK;
 | 
						|
#endif
 | 
						|
 | 
						|
  if (!mTabChild)
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
 | 
						|
  // While a plugin has focus, selection change notification shouldn't be
 | 
						|
  // available.
 | 
						|
  if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  // Note that selection change must be notified after text change if it occurs.
 | 
						|
  // Therefore, we don't need to query text content again here.
 | 
						|
  mContentCache.SetSelection(
 | 
						|
    this, 
 | 
						|
    aIMENotification.mSelectionChangeData.mOffset,
 | 
						|
    aIMENotification.mSelectionChangeData.Length(),
 | 
						|
    aIMENotification.mSelectionChangeData.mReversed,
 | 
						|
    aIMENotification.mSelectionChangeData.GetWritingMode());
 | 
						|
 | 
						|
  mTabChild->SendNotifyIMESelection(mContentCache, aIMENotification);
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::NotifyIMEOfMouseButtonEvent(
 | 
						|
                const IMENotification& aIMENotification)
 | 
						|
{
 | 
						|
  if (!mTabChild) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  // While a plugin has focus, mouse button event notification shouldn't be
 | 
						|
  // available.
 | 
						|
  if (NS_WARN_IF(mInputContext.mIMEState.mEnabled == IMEState::PLUGIN)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  bool consumedByIME = false;
 | 
						|
  if (!mTabChild->SendNotifyIMEMouseButtonEvent(aIMENotification,
 | 
						|
                                                &consumedByIME)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  return consumedByIME ? NS_SUCCESS_EVENT_CONSUMED : NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::NotifyIMEOfPositionChange(const IMENotification& aIMENotification)
 | 
						|
{
 | 
						|
#ifndef MOZ_CROSS_PROCESS_IME
 | 
						|
  return NS_OK;
 | 
						|
#endif
 | 
						|
  if (NS_WARN_IF(!mTabChild)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (NS_WARN_IF(!mContentCache.CacheEditorRect(this, &aIMENotification))) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  // While a plugin has focus, selection range isn't available.  So, we don't
 | 
						|
  // need to cache it at that time.
 | 
						|
  if (mInputContext.mIMEState.mEnabled != IMEState::PLUGIN &&
 | 
						|
      NS_WARN_IF(!mContentCache.CacheSelection(this, &aIMENotification))) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  if (mIMEPreferenceOfParent.WantPositionChanged()) {
 | 
						|
    mTabChild->SendNotifyIMEPositionChange(mContentCache, aIMENotification);
 | 
						|
  } else {
 | 
						|
    mTabChild->SendUpdateContentCache(mContentCache);
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::SetCursor(nsCursor aCursor)
 | 
						|
{
 | 
						|
  // Don't cache on windows, Windowless flash breaks this via async cursor updates.
 | 
						|
#if !defined(XP_WIN)
 | 
						|
  if (mCursor == aCursor && !mCustomCursor && !mUpdateCursor) {
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  mCustomCursor = nullptr;
 | 
						|
 | 
						|
  if (mTabChild &&
 | 
						|
      !mTabChild->SendSetCursor(aCursor, mUpdateCursor)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  mCursor = aCursor;
 | 
						|
  mUpdateCursor = false;
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::SetCursor(imgIContainer* aCursor,
 | 
						|
                        uint32_t aHotspotX, uint32_t aHotspotY)
 | 
						|
{
 | 
						|
  if (!aCursor || !mTabChild) {
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
 | 
						|
#if !defined(XP_WIN)
 | 
						|
  if (mCustomCursor == aCursor &&
 | 
						|
      mCursorHotspotX == aHotspotX &&
 | 
						|
      mCursorHotspotY == aHotspotY &&
 | 
						|
      !mUpdateCursor) {
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
  RefPtr<mozilla::gfx::SourceSurface> surface =
 | 
						|
    aCursor->GetFrame(imgIContainer::FRAME_CURRENT,
 | 
						|
                      imgIContainer::FLAG_SYNC_DECODE);
 | 
						|
  if (!surface) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  RefPtr<mozilla::gfx::DataSourceSurface> dataSurface =
 | 
						|
    surface->GetDataSurface();
 | 
						|
  if (!dataSurface) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  size_t length;
 | 
						|
  int32_t stride;
 | 
						|
  mozilla::UniquePtr<char[]> surfaceData =
 | 
						|
    nsContentUtils::GetSurfaceData(WrapNotNull(dataSurface), &length, &stride);
 | 
						|
 | 
						|
  nsDependentCString cursorData(surfaceData.get(), length);
 | 
						|
  mozilla::gfx::IntSize size = dataSurface->GetSize();
 | 
						|
  if (!mTabChild->SendSetCustomCursor(cursorData, size.width, size.height, stride,
 | 
						|
                                      static_cast<uint8_t>(dataSurface->GetFormat()),
 | 
						|
                                      aHotspotX, aHotspotY, mUpdateCursor)) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
 | 
						|
  mCursor = nsCursor(-1);
 | 
						|
  mCustomCursor = aCursor;
 | 
						|
  mCursorHotspotX = aHotspotX;
 | 
						|
  mCursorHotspotY = aHotspotY;
 | 
						|
  mUpdateCursor = false;
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::ClearCachedCursor()
 | 
						|
{
 | 
						|
  nsBaseWidget::ClearCachedCursor();
 | 
						|
  mCustomCursor = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::Paint()
 | 
						|
{
 | 
						|
  MOZ_ASSERT(!mDirtyRegion.IsEmpty(), "paint event logic messed up");
 | 
						|
 | 
						|
  if (!GetCurrentWidgetListener())
 | 
						|
    return NS_OK;
 | 
						|
 | 
						|
  LayoutDeviceIntRegion region = mDirtyRegion;
 | 
						|
 | 
						|
  // reset repaint tracking
 | 
						|
  mDirtyRegion.SetEmpty();
 | 
						|
  mPaintTask.Revoke();
 | 
						|
 | 
						|
  RefPtr<PuppetWidget> strongThis(this);
 | 
						|
 | 
						|
  GetCurrentWidgetListener()->WillPaintWindow(this);
 | 
						|
 | 
						|
  if (GetCurrentWidgetListener()) {
 | 
						|
#ifdef DEBUG
 | 
						|
    debug_DumpPaintEvent(stderr, this, region.ToUnknownRegion(),
 | 
						|
                         "PuppetWidget", 0);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (mozilla::layers::LayersBackend::LAYERS_CLIENT == mLayerManager->GetBackendType()) {
 | 
						|
      // Do nothing, the compositor will handle drawing
 | 
						|
      if (mTabChild) {
 | 
						|
        mTabChild->NotifyPainted();
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(mDrawTarget);
 | 
						|
      if (!ctx) {
 | 
						|
        gfxDevCrash(LogReason::InvalidContext) << "PuppetWidget context problem " << gfx::hexa(mDrawTarget);
 | 
						|
        return NS_ERROR_FAILURE;
 | 
						|
      }
 | 
						|
      ctx->Rectangle(gfxRect(0,0,0,0));
 | 
						|
      ctx->Clip();
 | 
						|
      AutoLayerManagerSetup setupLayerManager(this, ctx,
 | 
						|
                                              BufferMode::BUFFER_NONE);
 | 
						|
      GetCurrentWidgetListener()->PaintWindow(this, region);
 | 
						|
      if (mTabChild) {
 | 
						|
        mTabChild->NotifyPainted();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (GetCurrentWidgetListener()) {
 | 
						|
    GetCurrentWidgetListener()->DidPaintWindow();
 | 
						|
  }
 | 
						|
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::SetChild(PuppetWidget* aChild)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(this != aChild, "can't parent a widget to itself");
 | 
						|
  MOZ_ASSERT(!aChild->mChild,
 | 
						|
             "fake widget 'hierarchy' only expected to have one level");
 | 
						|
 | 
						|
  mChild = aChild;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::PaintTask::Run()
 | 
						|
{
 | 
						|
  if (mWidget) {
 | 
						|
    mWidget->Paint();
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS(PuppetWidget::MemoryPressureObserver, nsIObserver)
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetWidget::MemoryPressureObserver::Observe(nsISupports* aSubject,
 | 
						|
                                              const char* aTopic,
 | 
						|
                                              const char16_t* aData)
 | 
						|
{
 | 
						|
  if (!mWidget) {
 | 
						|
    return NS_OK;
 | 
						|
  }
 | 
						|
 | 
						|
  if (strcmp("memory-pressure", aTopic) == 0 &&
 | 
						|
      !NS_LITERAL_STRING("lowering-priority").Equals(aData)) {
 | 
						|
    if (!mWidget->mVisible && mWidget->mLayerManager &&
 | 
						|
        XRE_IsContentProcess()) {
 | 
						|
      mWidget->mLayerManager->ClearCachedResources();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::MemoryPressureObserver::Remove()
 | 
						|
{
 | 
						|
  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
 | 
						|
  if (obs) {
 | 
						|
    obs->RemoveObserver(this, "memory-pressure");
 | 
						|
  }
 | 
						|
  mWidget = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
PuppetWidget::NeedsPaint()
 | 
						|
{
 | 
						|
  // e10s popups are handled by the parent process, so never should be painted here
 | 
						|
  if (XRE_IsContentProcess() &&
 | 
						|
      Preferences::GetBool("browser.tabs.remote.desktopbehavior", false) &&
 | 
						|
      mWindowType == eWindowType_popup) {
 | 
						|
    NS_WARNING("Trying to paint an e10s popup in the child process!");
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  return mVisible;
 | 
						|
}
 | 
						|
 | 
						|
float
 | 
						|
PuppetWidget::GetDPI()
 | 
						|
{
 | 
						|
  if (mDPI < 0) {
 | 
						|
    if (mTabChild) {
 | 
						|
      mTabChild->GetDPI(&mDPI);
 | 
						|
    } else {
 | 
						|
      mDPI = 96.0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return mDPI;
 | 
						|
}
 | 
						|
 | 
						|
double
 | 
						|
PuppetWidget::GetDefaultScaleInternal()
 | 
						|
{
 | 
						|
  if (mDefaultScale < 0) {
 | 
						|
    if (mTabChild) {
 | 
						|
      mTabChild->GetDefaultScale(&mDefaultScale);
 | 
						|
    } else {
 | 
						|
      mDefaultScale = 1;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return mDefaultScale;
 | 
						|
}
 | 
						|
 | 
						|
void*
 | 
						|
PuppetWidget::GetNativeData(uint32_t aDataType)
 | 
						|
{
 | 
						|
  switch (aDataType) {
 | 
						|
  case NS_NATIVE_SHAREABLE_WINDOW: {
 | 
						|
    MOZ_ASSERT(mTabChild, "Need TabChild to get the nativeWindow from!");
 | 
						|
    mozilla::WindowsHandle nativeData = 0;
 | 
						|
    if (mTabChild) {
 | 
						|
      mTabChild->SendGetWidgetNativeData(&nativeData);
 | 
						|
    }
 | 
						|
    return (void*)nativeData;
 | 
						|
  }
 | 
						|
  case NS_NATIVE_WINDOW:
 | 
						|
  case NS_NATIVE_WIDGET:
 | 
						|
  case NS_NATIVE_DISPLAY:
 | 
						|
    // These types are ignored (see bug 1183828, bug 1240891).
 | 
						|
    break;
 | 
						|
  case NS_RAW_NATIVE_IME_CONTEXT:
 | 
						|
    MOZ_CRASH("You need to call GetNativeIMEContext() instead");
 | 
						|
  case NS_NATIVE_PLUGIN_PORT:
 | 
						|
  case NS_NATIVE_GRAPHIC:
 | 
						|
  case NS_NATIVE_SHELLWIDGET:
 | 
						|
  default:
 | 
						|
    NS_WARNING("nsWindow::GetNativeData called with bad value");
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
#if defined(XP_WIN)
 | 
						|
void
 | 
						|
PuppetWidget::SetNativeData(uint32_t aDataType, uintptr_t aVal)
 | 
						|
{
 | 
						|
  switch (aDataType) {
 | 
						|
  case NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW:
 | 
						|
    MOZ_ASSERT(mTabChild, "Need TabChild to send the message.");
 | 
						|
    if (mTabChild) {
 | 
						|
      mTabChild->SendSetNativeChildOfShareableWindow(aVal);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    NS_WARNING("SetNativeData called with unsupported data type.");
 | 
						|
  }
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
nsIntPoint
 | 
						|
PuppetWidget::GetChromeDimensions()
 | 
						|
{
 | 
						|
  if (!GetOwningTabChild()) {
 | 
						|
    NS_WARNING("PuppetWidget without Tab does not have chrome information.");
 | 
						|
    return nsIntPoint();
 | 
						|
  }
 | 
						|
  return GetOwningTabChild()->GetChromeDisplacement().ToUnknownPoint();
 | 
						|
}
 | 
						|
 | 
						|
nsIntPoint
 | 
						|
PuppetWidget::GetWindowPosition()
 | 
						|
{
 | 
						|
  if (!GetOwningTabChild()) {
 | 
						|
    return nsIntPoint();
 | 
						|
  }
 | 
						|
 | 
						|
  int32_t winX, winY, winW, winH;
 | 
						|
  NS_ENSURE_SUCCESS(GetOwningTabChild()->GetDimensions(0, &winX, &winY, &winW, &winH), nsIntPoint());
 | 
						|
  return nsIntPoint(winX, winY) + GetOwningTabChild()->GetClientOffset().ToUnknownPoint();
 | 
						|
}
 | 
						|
 | 
						|
LayoutDeviceIntRect
 | 
						|
PuppetWidget::GetScreenBounds()
 | 
						|
{
 | 
						|
  return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds.Size());
 | 
						|
}
 | 
						|
 | 
						|
uint32_t PuppetWidget::GetMaxTouchPoints() const
 | 
						|
{
 | 
						|
  static uint32_t sTouchPoints = 0;
 | 
						|
  static bool sIsInitialized = false;
 | 
						|
  if (sIsInitialized) {
 | 
						|
    return sTouchPoints;
 | 
						|
  }
 | 
						|
  if (mTabChild) {
 | 
						|
    mTabChild->GetMaxTouchPoints(&sTouchPoints);
 | 
						|
    sIsInitialized = true;
 | 
						|
  }
 | 
						|
  return sTouchPoints;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics)
 | 
						|
{
 | 
						|
  mTabChild->StartScrollbarDrag(aDragMetrics);
 | 
						|
}
 | 
						|
 | 
						|
PuppetScreen::PuppetScreen(void *nativeScreen)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
PuppetScreen::~PuppetScreen()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static ScreenConfiguration
 | 
						|
ScreenConfig()
 | 
						|
{
 | 
						|
  ScreenConfiguration config;
 | 
						|
  hal::GetCurrentScreenConfiguration(&config);
 | 
						|
  return config;
 | 
						|
}
 | 
						|
 | 
						|
nsIntSize
 | 
						|
PuppetWidget::GetScreenDimensions()
 | 
						|
{
 | 
						|
  nsIntRect r = ScreenConfig().rect();
 | 
						|
  return nsIntSize(r.width, r.height);
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreen::GetId(uint32_t *outId)
 | 
						|
{
 | 
						|
  *outId = 1;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreen::GetRect(int32_t *outLeft,  int32_t *outTop,
 | 
						|
                      int32_t *outWidth, int32_t *outHeight)
 | 
						|
{
 | 
						|
  nsIntRect r = ScreenConfig().rect();
 | 
						|
  *outLeft = r.x;
 | 
						|
  *outTop = r.y;
 | 
						|
  *outWidth = r.width;
 | 
						|
  *outHeight = r.height;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreen::GetAvailRect(int32_t *outLeft,  int32_t *outTop,
 | 
						|
                           int32_t *outWidth, int32_t *outHeight)
 | 
						|
{
 | 
						|
  return GetRect(outLeft, outTop, outWidth, outHeight);
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreen::GetPixelDepth(int32_t *aPixelDepth)
 | 
						|
{
 | 
						|
  *aPixelDepth = ScreenConfig().pixelDepth();
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreen::GetColorDepth(int32_t *aColorDepth)
 | 
						|
{
 | 
						|
  *aColorDepth = ScreenConfig().colorDepth();
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreen::GetRotation(uint32_t* aRotation)
 | 
						|
{
 | 
						|
  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.");
 | 
						|
  return NS_ERROR_NOT_AVAILABLE;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreen::SetRotation(uint32_t aRotation)
 | 
						|
{
 | 
						|
  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.");
 | 
						|
  return NS_ERROR_NOT_AVAILABLE;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMPL_ISUPPORTS(PuppetScreenManager, nsIScreenManager)
 | 
						|
 | 
						|
PuppetScreenManager::PuppetScreenManager()
 | 
						|
{
 | 
						|
    mOneScreen = new PuppetScreen(nullptr);
 | 
						|
}
 | 
						|
 | 
						|
PuppetScreenManager::~PuppetScreenManager()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreenManager::ScreenForId(uint32_t aId,
 | 
						|
                                 nsIScreen** outScreen)
 | 
						|
{
 | 
						|
  NS_IF_ADDREF(*outScreen = mOneScreen.get());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreenManager::GetPrimaryScreen(nsIScreen** outScreen)
 | 
						|
{
 | 
						|
  NS_IF_ADDREF(*outScreen = mOneScreen.get());
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreenManager::ScreenForRect(int32_t inLeft,
 | 
						|
                                   int32_t inTop,
 | 
						|
                                   int32_t inWidth,
 | 
						|
                                   int32_t inHeight,
 | 
						|
                                   nsIScreen** outScreen)
 | 
						|
{
 | 
						|
  return GetPrimaryScreen(outScreen);
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreenManager::ScreenForNativeWidget(void* aWidget,
 | 
						|
                                           nsIScreen** outScreen)
 | 
						|
{
 | 
						|
  return GetPrimaryScreen(outScreen);
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreenManager::GetNumberOfScreens(uint32_t* aNumberOfScreens)
 | 
						|
{
 | 
						|
  *aNumberOfScreens = 1;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
NS_IMETHODIMP
 | 
						|
PuppetScreenManager::GetSystemDefaultScale(float *aDefaultScale)
 | 
						|
{
 | 
						|
  *aDefaultScale = 1.0f;
 | 
						|
  return NS_OK;
 | 
						|
}
 | 
						|
 | 
						|
nsIWidgetListener*
 | 
						|
PuppetWidget::GetCurrentWidgetListener()
 | 
						|
{
 | 
						|
  if (!mPreviouslyAttachedWidgetListener ||
 | 
						|
      !mAttachedWidgetListener) {
 | 
						|
    return mAttachedWidgetListener;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mAttachedWidgetListener->GetView()->IsPrimaryFramePaintSuppressed()) {
 | 
						|
    return mPreviouslyAttachedWidgetListener;
 | 
						|
  }
 | 
						|
 | 
						|
  return mAttachedWidgetListener;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::SetCandidateWindowForPlugin(
 | 
						|
                const CandidateWindowPosition& aPosition)
 | 
						|
{
 | 
						|
  if (!mTabChild) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mTabChild->SendSetCandidateWindowForPlugin(aPosition);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::ZoomToRect(const uint32_t& aPresShellId,
 | 
						|
                         const FrameMetrics::ViewID& aViewId,
 | 
						|
                         const CSSRect& aRect,
 | 
						|
                         const uint32_t& aFlags)
 | 
						|
{
 | 
						|
  if (!mTabChild) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mTabChild->ZoomToRect(aPresShellId, aViewId, aRect, aFlags);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::LookUpDictionary(
 | 
						|
                const nsAString& aText,
 | 
						|
                const nsTArray<mozilla::FontRange>& aFontRangeArray,
 | 
						|
                const bool aIsVertical,
 | 
						|
                const LayoutDeviceIntPoint& aPoint)
 | 
						|
{
 | 
						|
  if (!mTabChild) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mTabChild->SendLookUpDictionary(nsString(aText), aFontRangeArray, aIsVertical, aPoint);
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
PuppetWidget::HasPendingInputEvent()
 | 
						|
{
 | 
						|
  if (!mTabChild) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  bool ret = false;
 | 
						|
 | 
						|
  mTabChild->GetIPCChannel()->PeekMessages(
 | 
						|
    [&ret](const IPC::Message& aMsg) -> bool {
 | 
						|
      if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart)
 | 
						|
          == mozilla::dom::PBrowser::PBrowserStart) {
 | 
						|
        switch (aMsg.type()) {
 | 
						|
          case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_SynthMouseMoveEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_MouseEvent__ID:
 | 
						|
          case mozilla::dom::PBrowser::Msg_KeyEvent__ID:
 | 
						|
            ret = true;
 | 
						|
            return false;  // Stop peeking.
 | 
						|
        }
 | 
						|
      }
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  );
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
PuppetWidget::HandledWindowedPluginKeyEvent(
 | 
						|
                const NativeEventData& aKeyEventData,
 | 
						|
                bool aIsConsumed)
 | 
						|
{
 | 
						|
  if (NS_WARN_IF(mKeyEventInPluginCallbacks.IsEmpty())) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  nsCOMPtr<nsIKeyEventInPluginCallback> callback =
 | 
						|
    mKeyEventInPluginCallbacks[0];
 | 
						|
  MOZ_ASSERT(callback);
 | 
						|
  mKeyEventInPluginCallbacks.RemoveElementAt(0);
 | 
						|
  callback->HandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
 | 
						|
}
 | 
						|
 | 
						|
nsresult
 | 
						|
PuppetWidget::OnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
 | 
						|
                                       nsIKeyEventInPluginCallback* aCallback)
 | 
						|
{
 | 
						|
  if (NS_WARN_IF(!mTabChild)) {
 | 
						|
    return NS_ERROR_NOT_AVAILABLE;
 | 
						|
  }
 | 
						|
  if (NS_WARN_IF(!mTabChild->SendOnWindowedPluginKeyEvent(aKeyEventData))) {
 | 
						|
    return NS_ERROR_FAILURE;
 | 
						|
  }
 | 
						|
  mKeyEventInPluginCallbacks.AppendElement(aCallback);
 | 
						|
  return NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace widget
 | 
						|
} // namespace mozilla
 |