layout/generic/nsObjectFrame.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/layout/generic/nsObjectFrame.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2063 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +// vim:set ts=2 sts=2 sw=2 et cin:
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/* rendering objects for replaced elements implemented by a plugin */
    1.11 +
    1.12 +#include "nsObjectFrame.h"
    1.13 +
    1.14 +#include "gfx2DGlue.h"
    1.15 +#include "mozilla/BasicEvents.h"
    1.16 +#ifdef XP_WIN
    1.17 +// This is needed for DoublePassRenderingEvent.
    1.18 +#include "mozilla/plugins/PluginMessageUtils.h"
    1.19 +#endif
    1.20 +
    1.21 +#include "nscore.h"
    1.22 +#include "nsCOMPtr.h"
    1.23 +#include "nsPresContext.h"
    1.24 +#include "nsIPresShell.h"
    1.25 +#include "nsWidgetsCID.h"
    1.26 +#include "nsView.h"
    1.27 +#include "nsViewManager.h"
    1.28 +#include "nsString.h"
    1.29 +#include "nsGkAtoms.h"
    1.30 +#include "nsIPluginInstanceOwner.h"
    1.31 +#include "nsNPAPIPluginInstance.h"
    1.32 +#include "nsIDOMElement.h"
    1.33 +#include "nsRenderingContext.h"
    1.34 +#include "npapi.h"
    1.35 +#include "nsIObjectLoadingContent.h"
    1.36 +#include "nsContentUtils.h"
    1.37 +#include "nsDisplayList.h"
    1.38 +#include "nsFocusManager.h"
    1.39 +#include "nsLayoutUtils.h"
    1.40 +#include "nsFrameManager.h"
    1.41 +#include "nsIObserverService.h"
    1.42 +#include "GeckoProfiler.h"
    1.43 +#include <algorithm>
    1.44 +
    1.45 +#include "nsIObjectFrame.h"
    1.46 +#include "nsPluginNativeWindow.h"
    1.47 +#include "FrameLayerBuilder.h"
    1.48 +
    1.49 +#include "ImageLayers.h"
    1.50 +#include "nsPluginInstanceOwner.h"
    1.51 +
    1.52 +#ifdef XP_WIN
    1.53 +#include "gfxWindowsNativeDrawing.h"
    1.54 +#include "gfxWindowsSurface.h"
    1.55 +#endif
    1.56 +
    1.57 +#include "Layers.h"
    1.58 +#include "ReadbackLayer.h"
    1.59 +#include "ImageContainer.h"
    1.60 +
    1.61 +// accessibility support
    1.62 +#ifdef ACCESSIBILITY
    1.63 +#include "nsAccessibilityService.h"
    1.64 +#endif
    1.65 +
    1.66 +#ifdef MOZ_LOGGING
    1.67 +#define FORCE_PR_LOG 1 /* Allow logging in the release build */
    1.68 +#endif /* MOZ_LOGGING */
    1.69 +#include "prlog.h"
    1.70 +
    1.71 +#ifdef XP_MACOSX
    1.72 +#include "gfxQuartzNativeDrawing.h"
    1.73 +#include "nsPluginUtilsOSX.h"
    1.74 +#include "mozilla/gfx/QuartzSupport.h"
    1.75 +#endif
    1.76 +
    1.77 +#ifdef MOZ_X11
    1.78 +#include "mozilla/X11Util.h"
    1.79 +using mozilla::DefaultXDisplay;
    1.80 +#endif
    1.81 +
    1.82 +#ifdef XP_WIN
    1.83 +#include <wtypes.h>
    1.84 +#include <winuser.h>
    1.85 +#endif
    1.86 +
    1.87 +#ifdef MOZ_WIDGET_ANDROID
    1.88 +#include "AndroidBridge.h"
    1.89 +#include "GLContext.h"
    1.90 +#endif
    1.91 +
    1.92 +#ifdef CreateEvent // Thank you MS.
    1.93 +#undef CreateEvent
    1.94 +#endif
    1.95 +
    1.96 +#ifdef PR_LOGGING 
    1.97 +static PRLogModuleInfo *
    1.98 +GetObjectFrameLog()
    1.99 +{
   1.100 +  static PRLogModuleInfo *sLog;
   1.101 +  if (!sLog)
   1.102 +    sLog = PR_NewLogModule("nsObjectFrame");
   1.103 +  return sLog;
   1.104 +}
   1.105 +#endif /* PR_LOGGING */
   1.106 +
   1.107 +#if defined(XP_MACOSX) && !defined(__LP64__)
   1.108 +
   1.109 +// The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
   1.110 +// and up (though the QuickDraw APIs defined in them are still present) -- so
   1.111 +// we need to supply the relevant parts of their contents here.  It's likely
   1.112 +// that Apple will eventually remove the APIs themselves (probably in OS X
   1.113 +// 10.8), so we need to make them weak imports, and test for their presence
   1.114 +// before using them.
   1.115 +extern "C" {
   1.116 +  #if !defined(__QUICKDRAWAPI__)
   1.117 +  extern void SetRect(
   1.118 +    Rect * r,
   1.119 +    short  left,
   1.120 +    short  top,
   1.121 +    short  right,
   1.122 +    short  bottom)
   1.123 +    __attribute__((weak_import));
   1.124 +  #endif /* __QUICKDRAWAPI__ */
   1.125 +
   1.126 +  #if !defined(__QDOFFSCREEN__)
   1.127 +  extern QDErr NewGWorldFromPtr(
   1.128 +    GWorldPtr *   offscreenGWorld,
   1.129 +    UInt32        PixelFormat,
   1.130 +    const Rect *  boundsRect,
   1.131 +    CTabHandle    cTable,                /* can be nullptr */
   1.132 +    GDHandle      aGDevice,              /* can be nullptr */
   1.133 +    GWorldFlags   flags,
   1.134 +    Ptr           newBuffer,
   1.135 +    SInt32        rowBytes)
   1.136 +    __attribute__((weak_import));
   1.137 +  extern void DisposeGWorld(GWorldPtr offscreenGWorld)
   1.138 +    __attribute__((weak_import));
   1.139 +  #endif /* __QDOFFSCREEN__ */
   1.140 +}
   1.141 +
   1.142 +#endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */
   1.143 +
   1.144 +using namespace mozilla;
   1.145 +using namespace mozilla::gfx;
   1.146 +using namespace mozilla::layers;
   1.147 +
   1.148 +class PluginBackgroundSink : public ReadbackSink {
   1.149 +public:
   1.150 +  PluginBackgroundSink(nsObjectFrame* aFrame, uint64_t aStartSequenceNumber)
   1.151 +    : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
   1.152 +  ~PluginBackgroundSink()
   1.153 +  {
   1.154 +    if (mFrame) {
   1.155 +      mFrame->mBackgroundSink = nullptr;
   1.156 +    }
   1.157 +  }
   1.158 +
   1.159 +  virtual void SetUnknown(uint64_t aSequenceNumber)
   1.160 +  {
   1.161 +    if (!AcceptUpdate(aSequenceNumber))
   1.162 +      return;
   1.163 +    mFrame->mInstanceOwner->SetBackgroundUnknown();
   1.164 +  }
   1.165 +
   1.166 +  virtual already_AddRefed<gfxContext>
   1.167 +      BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber)
   1.168 +  {
   1.169 +    if (!AcceptUpdate(aSequenceNumber))
   1.170 +      return nullptr;
   1.171 +    return mFrame->mInstanceOwner->BeginUpdateBackground(aRect);
   1.172 +  }
   1.173 +
   1.174 +  virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect)
   1.175 +  {
   1.176 +    return mFrame->mInstanceOwner->EndUpdateBackground(aContext, aRect);
   1.177 +  }
   1.178 +
   1.179 +  void Destroy() { mFrame = nullptr; }
   1.180 +
   1.181 +protected:
   1.182 +  bool AcceptUpdate(uint64_t aSequenceNumber) {
   1.183 +    if (aSequenceNumber > mLastSequenceNumber && mFrame &&
   1.184 +        mFrame->mInstanceOwner) {
   1.185 +      mLastSequenceNumber = aSequenceNumber;
   1.186 +      return true;
   1.187 +    }
   1.188 +    return false;
   1.189 +  }
   1.190 +
   1.191 +  uint64_t mLastSequenceNumber;
   1.192 +  nsObjectFrame* mFrame;
   1.193 +};
   1.194 +
   1.195 +nsObjectFrame::nsObjectFrame(nsStyleContext* aContext)
   1.196 +  : nsObjectFrameSuper(aContext)
   1.197 +  , mReflowCallbackPosted(false)
   1.198 +{
   1.199 +  PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
   1.200 +         ("Created new nsObjectFrame %p\n", this));
   1.201 +}
   1.202 +
   1.203 +nsObjectFrame::~nsObjectFrame()
   1.204 +{
   1.205 +  PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
   1.206 +         ("nsObjectFrame %p deleted\n", this));
   1.207 +}
   1.208 +
   1.209 +NS_QUERYFRAME_HEAD(nsObjectFrame)
   1.210 +  NS_QUERYFRAME_ENTRY(nsObjectFrame)
   1.211 +  NS_QUERYFRAME_ENTRY(nsIObjectFrame)
   1.212 +NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper)
   1.213 +
   1.214 +#ifdef ACCESSIBILITY
   1.215 +a11y::AccType
   1.216 +nsObjectFrame::AccessibleType()
   1.217 +{
   1.218 +  return a11y::ePluginType;
   1.219 +}
   1.220 +
   1.221 +#ifdef XP_WIN
   1.222 +NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
   1.223 +{
   1.224 +  *aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
   1.225 +  return NS_OK;
   1.226 +}
   1.227 +#endif
   1.228 +#endif
   1.229 +
   1.230 +void
   1.231 +nsObjectFrame::Init(nsIContent*      aContent,
   1.232 +                    nsIFrame*        aParent,
   1.233 +                    nsIFrame*        aPrevInFlow)
   1.234 +{
   1.235 +  PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
   1.236 +         ("Initializing nsObjectFrame %p for content %p\n", this, aContent));
   1.237 +
   1.238 +  nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
   1.239 +}
   1.240 +
   1.241 +void
   1.242 +nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
   1.243 +{
   1.244 +  if (mReflowCallbackPosted) {
   1.245 +    PresContext()->PresShell()->CancelReflowCallback(this);
   1.246 +  }
   1.247 +
   1.248 +  // Tell content owner of the instance to disconnect its frame.
   1.249 +  nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
   1.250 +  NS_ASSERTION(objContent, "Why not an object loading content?");
   1.251 +
   1.252 +  // The content might not have a reference to the instance owner any longer in
   1.253 +  // the case of re-entry during instantiation or teardown, so make sure we're
   1.254 +  // dissociated.
   1.255 +  if (mInstanceOwner) {
   1.256 +    mInstanceOwner->SetFrame(nullptr);
   1.257 +  }
   1.258 +  objContent->HasNewFrame(nullptr);
   1.259 +
   1.260 +  if (mBackgroundSink) {
   1.261 +    mBackgroundSink->Destroy();
   1.262 +  }
   1.263 +
   1.264 +  nsObjectFrameSuper::DestroyFrom(aDestructRoot);
   1.265 +}
   1.266 +
   1.267 +/* virtual */ void
   1.268 +nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
   1.269 +{
   1.270 +  if (HasView()) {
   1.271 +    nsView* view = GetView();
   1.272 +    nsViewManager* vm = view->GetViewManager();
   1.273 +    if (vm) {
   1.274 +      nsViewVisibility visibility = 
   1.275 +        IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
   1.276 +      vm->SetViewVisibility(view, visibility);
   1.277 +    }
   1.278 +  }
   1.279 +
   1.280 +  nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext);
   1.281 +}
   1.282 +
   1.283 +nsIAtom*
   1.284 +nsObjectFrame::GetType() const
   1.285 +{
   1.286 +  return nsGkAtoms::objectFrame; 
   1.287 +}
   1.288 +
   1.289 +#ifdef DEBUG_FRAME_DUMP
   1.290 +nsresult
   1.291 +nsObjectFrame::GetFrameName(nsAString& aResult) const
   1.292 +{
   1.293 +  return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult);
   1.294 +}
   1.295 +#endif
   1.296 +
   1.297 +nsresult
   1.298 +nsObjectFrame::PrepForDrawing(nsIWidget *aWidget)
   1.299 +{
   1.300 +  mWidget = aWidget;
   1.301 +
   1.302 +  nsView* view = GetView();
   1.303 +  NS_ASSERTION(view, "Object frames must have views");  
   1.304 +  if (!view) {
   1.305 +    return NS_ERROR_FAILURE;
   1.306 +  }
   1.307 +
   1.308 +  nsViewManager* viewMan = view->GetViewManager();
   1.309 +  // mark the view as hidden since we don't know the (x,y) until Paint
   1.310 +  // XXX is the above comment correct?
   1.311 +  viewMan->SetViewVisibility(view, nsViewVisibility_kHide);
   1.312 +
   1.313 +  //this is ugly. it was ripped off from didreflow(). MMP
   1.314 +  // Position and size view relative to its parent, not relative to our
   1.315 +  // parent frame (our parent frame may not have a view).
   1.316 +  
   1.317 +  nsView* parentWithView;
   1.318 +  nsPoint origin;
   1.319 +  nsRect r(0, 0, mRect.width, mRect.height);
   1.320 +
   1.321 +  GetOffsetFromView(origin, &parentWithView);
   1.322 +  viewMan->ResizeView(view, r);
   1.323 +  viewMan->MoveViewTo(view, origin.x, origin.y);
   1.324 +
   1.325 +  nsPresContext* presContext = PresContext();
   1.326 +  nsRootPresContext* rpc = presContext->GetRootPresContext();
   1.327 +  if (!rpc) {
   1.328 +    return NS_ERROR_FAILURE;
   1.329 +  }
   1.330 +
   1.331 +  if (mWidget) {
   1.332 +    // Disallow windowed plugins in popups
   1.333 +    nsIFrame* rootFrame = rpc->PresShell()->FrameManager()->GetRootFrame();
   1.334 +    nsIWidget* parentWidget = rootFrame->GetNearestWidget();
   1.335 +    if (!parentWidget || nsLayoutUtils::GetDisplayRootFrame(this) != rootFrame) {
   1.336 +      return NS_ERROR_FAILURE;
   1.337 +    }
   1.338 +
   1.339 +    mInnerView = viewMan->CreateView(GetContentRectRelativeToSelf(), view);
   1.340 +    if (!mInnerView) {
   1.341 +      NS_ERROR("Could not create inner view");
   1.342 +      return NS_ERROR_OUT_OF_MEMORY;
   1.343 +    }
   1.344 +    viewMan->InsertChild(view, mInnerView, nullptr, true);
   1.345 +
   1.346 +    mWidget->SetParent(parentWidget);
   1.347 +    mWidget->Show(true);
   1.348 +    mWidget->Enable(true);
   1.349 +
   1.350 +    // Set the plugin window to have an empty clip region until we know
   1.351 +    // what our true position, size and clip region are. These
   1.352 +    // will be reset when nsRootPresContext computes our true
   1.353 +    // geometry. The plugin window does need to have a good size here, so
   1.354 +    // set the size explicitly to a reasonable guess.
   1.355 +    nsAutoTArray<nsIWidget::Configuration,1> configurations;
   1.356 +    nsIWidget::Configuration* configuration = configurations.AppendElement();
   1.357 +    nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
   1.358 +    configuration->mChild = mWidget;
   1.359 +    configuration->mBounds.width = NSAppUnitsToIntPixels(mRect.width, appUnitsPerDevPixel);
   1.360 +    configuration->mBounds.height = NSAppUnitsToIntPixels(mRect.height, appUnitsPerDevPixel);
   1.361 +    parentWidget->ConfigureChildren(configurations);
   1.362 +
   1.363 +    nsRefPtr<nsDeviceContext> dx = viewMan->GetDeviceContext();
   1.364 +    mInnerView->AttachWidgetEventHandler(mWidget);
   1.365 +
   1.366 +#ifdef XP_MACOSX
   1.367 +    // On Mac, we need to invalidate ourselves since even windowed
   1.368 +    // plugins are painted through Thebes and we need to ensure
   1.369 +    // the Thebes layer containing the plugin is updated.
   1.370 +    if (parentWidget == GetNearestWidget()) {
   1.371 +      InvalidateFrame();
   1.372 +    }
   1.373 +#endif
   1.374 +
   1.375 +    RegisterPluginForGeometryUpdates();
   1.376 +
   1.377 +    // Here we set the background color for this widget because some plugins will use 
   1.378 +    // the child window background color when painting. If it's not set, it may default to gray
   1.379 +    // Sometimes, a frame doesn't have a background color or is transparent. In this
   1.380 +    // case, walk up the frame tree until we do find a frame with a background color
   1.381 +    for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
   1.382 +      nscolor bgcolor =
   1.383 +        frame->GetVisitedDependentColor(eCSSProperty_background_color);
   1.384 +      if (NS_GET_A(bgcolor) > 0) {  // make sure we got an actual color
   1.385 +        mWidget->SetBackgroundColor(bgcolor);
   1.386 +        break;
   1.387 +      }
   1.388 +    }
   1.389 +  } else {
   1.390 +    // Changing to windowless mode changes the NPWindow geometry.
   1.391 +    FixupWindow(GetContentRectRelativeToSelf().Size());
   1.392 +
   1.393 +#ifndef XP_MACOSX
   1.394 +    RegisterPluginForGeometryUpdates();
   1.395 +#endif
   1.396 +  }
   1.397 +
   1.398 +  if (!IsHidden()) {
   1.399 +    viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
   1.400 +  }
   1.401 +
   1.402 +#ifdef ACCESSIBILITY
   1.403 +  nsAccessibilityService* accService = nsIPresShell::AccService();
   1.404 +  if (accService) {
   1.405 +    accService->RecreateAccessible(PresContext()->PresShell(), mContent);
   1.406 +  }
   1.407 +#endif
   1.408 +
   1.409 +  return NS_OK;
   1.410 +}
   1.411 +
   1.412 +#define EMBED_DEF_WIDTH 240
   1.413 +#define EMBED_DEF_HEIGHT 200
   1.414 +
   1.415 +/* virtual */ nscoord
   1.416 +nsObjectFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
   1.417 +{
   1.418 +  nscoord result = 0;
   1.419 +
   1.420 +  if (!IsHidden(false)) {
   1.421 +    nsIAtom *atom = mContent->Tag();
   1.422 +    if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
   1.423 +      result = nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH);
   1.424 +    }
   1.425 +  }
   1.426 +
   1.427 +  DISPLAY_MIN_WIDTH(this, result);
   1.428 +  return result;
   1.429 +}
   1.430 +
   1.431 +/* virtual */ nscoord
   1.432 +nsObjectFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
   1.433 +{
   1.434 +  return nsObjectFrame::GetMinWidth(aRenderingContext);
   1.435 +}
   1.436 +
   1.437 +void
   1.438 +nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
   1.439 +                              const nsHTMLReflowState& aReflowState,
   1.440 +                              nsHTMLReflowMetrics& aMetrics)
   1.441 +{
   1.442 +  // By default, we have no area
   1.443 +  aMetrics.Width() = 0;
   1.444 +  aMetrics.Height() = 0;
   1.445 +
   1.446 +  if (IsHidden(false)) {
   1.447 +    return;
   1.448 +  }
   1.449 +  
   1.450 +  aMetrics.Width() = aReflowState.ComputedWidth();
   1.451 +  aMetrics.Height() = aReflowState.ComputedHeight();
   1.452 +
   1.453 +  // for EMBED and APPLET, default to 240x200 for compatibility
   1.454 +  nsIAtom *atom = mContent->Tag();
   1.455 +  if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
   1.456 +    if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
   1.457 +      aMetrics.Width() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
   1.458 +                               aReflowState.ComputedMinWidth(),
   1.459 +                               aReflowState.ComputedMaxWidth());
   1.460 +    }
   1.461 +    if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
   1.462 +      aMetrics.Height() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
   1.463 +                                aReflowState.ComputedMinHeight(),
   1.464 +                                aReflowState.ComputedMaxHeight());
   1.465 +    }
   1.466 +
   1.467 +#if defined(MOZ_WIDGET_GTK)
   1.468 +    // We need to make sure that the size of the object frame does not
   1.469 +    // exceed the maximum size of X coordinates.  See bug #225357 for
   1.470 +    // more information.  In theory Gtk2 can handle large coordinates,
   1.471 +    // but underlying plugins can't.
   1.472 +    aMetrics.Height() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Height());
   1.473 +    aMetrics.Width() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Width());
   1.474 +#endif
   1.475 +  }
   1.476 +
   1.477 +  // At this point, the width has an unconstrained value only if we have
   1.478 +  // nothing to go on (no width set, no information from the plugin, nothing).
   1.479 +  // Make up a number.
   1.480 +  if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
   1.481 +    aMetrics.Width() =
   1.482 +      (aReflowState.ComputedMinWidth() != NS_UNCONSTRAINEDSIZE) ?
   1.483 +        aReflowState.ComputedMinWidth() : 0;
   1.484 +  }
   1.485 +
   1.486 +  // At this point, the height has an unconstrained value only in two cases:
   1.487 +  // a) We are in standards mode with percent heights and parent is auto-height
   1.488 +  // b) We have no height information at all.
   1.489 +  // In either case, we have to make up a number.
   1.490 +  if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
   1.491 +    aMetrics.Height() =
   1.492 +      (aReflowState.ComputedMinHeight() != NS_UNCONSTRAINEDSIZE) ?
   1.493 +        aReflowState.ComputedMinHeight() : 0;
   1.494 +  }
   1.495 +
   1.496 +  // XXXbz don't add in the border and padding, because we screw up our
   1.497 +  // plugin's size and positioning if we do...  Eventually we _do_ want to
   1.498 +  // paint borders, though!  At that point, we will need to adjust the desired
   1.499 +  // size either here or in Reflow....  Further, we will need to fix Paint() to
   1.500 +  // call the superclass in all cases.
   1.501 +}
   1.502 +
   1.503 +nsresult
   1.504 +nsObjectFrame::Reflow(nsPresContext*           aPresContext,
   1.505 +                      nsHTMLReflowMetrics&     aMetrics,
   1.506 +                      const nsHTMLReflowState& aReflowState,
   1.507 +                      nsReflowStatus&          aStatus)
   1.508 +{
   1.509 +  DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
   1.510 +  DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
   1.511 +
   1.512 +  // Get our desired size
   1.513 +  GetDesiredSize(aPresContext, aReflowState, aMetrics);
   1.514 +  aMetrics.SetOverflowAreasToDesiredBounds();
   1.515 +  FinishAndStoreOverflow(&aMetrics);
   1.516 +
   1.517 +  // delay plugin instantiation until all children have
   1.518 +  // arrived. Otherwise there may be PARAMs or other stuff that the
   1.519 +  // plugin needs to see that haven't arrived yet.
   1.520 +  if (!GetContent()->IsDoneAddingChildren()) {
   1.521 +    aStatus = NS_FRAME_COMPLETE;
   1.522 +    return NS_OK;
   1.523 +  }
   1.524 +
   1.525 +  // if we are printing or print previewing, bail for now
   1.526 +  if (aPresContext->Medium() == nsGkAtoms::print) {
   1.527 +    aStatus = NS_FRAME_COMPLETE;
   1.528 +    return NS_OK;
   1.529 +  }
   1.530 +
   1.531 +  nsRect r(0, 0, aMetrics.Width(), aMetrics.Height());
   1.532 +  r.Deflate(aReflowState.ComputedPhysicalBorderPadding());
   1.533 +
   1.534 +  if (mInnerView) {
   1.535 +    nsViewManager* vm = mInnerView->GetViewManager();
   1.536 +    vm->MoveViewTo(mInnerView, r.x, r.y);
   1.537 +    vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), r.Size()), true);
   1.538 +  }
   1.539 +
   1.540 +  FixupWindow(r.Size());
   1.541 +  if (!mReflowCallbackPosted) {
   1.542 +    mReflowCallbackPosted = true;
   1.543 +    aPresContext->PresShell()->PostReflowCallback(this);
   1.544 +  }
   1.545 +
   1.546 +  aStatus = NS_FRAME_COMPLETE;
   1.547 +
   1.548 +  NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
   1.549 +  return NS_OK;
   1.550 +}
   1.551 +
   1.552 +///////////// nsIReflowCallback ///////////////
   1.553 +
   1.554 +bool
   1.555 +nsObjectFrame::ReflowFinished()
   1.556 +{
   1.557 +  mReflowCallbackPosted = false;
   1.558 +  CallSetWindow();
   1.559 +  return true;
   1.560 +}
   1.561 +
   1.562 +void
   1.563 +nsObjectFrame::ReflowCallbackCanceled()
   1.564 +{
   1.565 +  mReflowCallbackPosted = false;
   1.566 +}
   1.567 +
   1.568 +void
   1.569 +nsObjectFrame::FixupWindow(const nsSize& aSize)
   1.570 +{
   1.571 +  nsPresContext* presContext = PresContext();
   1.572 +
   1.573 +  if (!mInstanceOwner)
   1.574 +    return;
   1.575 +
   1.576 +  NPWindow *window;
   1.577 +  mInstanceOwner->GetWindow(window);
   1.578 +
   1.579 +  NS_ENSURE_TRUE_VOID(window);
   1.580 +
   1.581 +#ifdef XP_MACOSX
   1.582 +  nsWeakFrame weakFrame(this);
   1.583 +  mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
   1.584 +  if (!weakFrame.IsAlive()) {
   1.585 +    return;
   1.586 +  }
   1.587 +#endif
   1.588 +
   1.589 +  bool windowless = (window->type == NPWindowTypeDrawable);
   1.590 +
   1.591 +  nsIntPoint origin = GetWindowOriginInPixels(windowless);
   1.592 +
   1.593 +  // window must be in "display pixels"
   1.594 +  double scaleFactor = 1.0;
   1.595 +  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
   1.596 +    scaleFactor = 1.0;
   1.597 +  }
   1.598 +  int intScaleFactor = ceil(scaleFactor);
   1.599 +  window->x = origin.x / intScaleFactor;
   1.600 +  window->y = origin.y / intScaleFactor;
   1.601 +  window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
   1.602 +  window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
   1.603 +
   1.604 +  // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
   1.605 +  // us from drawing on screen until the widget is properly positioned, which will not
   1.606 +  // happen until we have finished the reflow process.
   1.607 +#ifdef XP_MACOSX
   1.608 +  window->clipRect.top = 0;
   1.609 +  window->clipRect.left = 0;
   1.610 +  window->clipRect.bottom = 0;
   1.611 +  window->clipRect.right = 0;
   1.612 +#else
   1.613 +  mInstanceOwner->UpdateWindowPositionAndClipRect(false);
   1.614 +#endif
   1.615 +
   1.616 +  NotifyPluginReflowObservers();
   1.617 +}
   1.618 +
   1.619 +nsresult
   1.620 +nsObjectFrame::CallSetWindow(bool aCheckIsHidden)
   1.621 +{
   1.622 +  NPWindow *win = nullptr;
   1.623 + 
   1.624 +  nsresult rv = NS_ERROR_FAILURE;
   1.625 +  nsRefPtr<nsNPAPIPluginInstance> pi;
   1.626 +  if (!mInstanceOwner ||
   1.627 +      NS_FAILED(rv = mInstanceOwner->GetInstance(getter_AddRefs(pi))) ||
   1.628 +      !pi ||
   1.629 +      NS_FAILED(rv = mInstanceOwner->GetWindow(win)) || 
   1.630 +      !win)
   1.631 +    return rv;
   1.632 +
   1.633 +  nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
   1.634 +#ifdef XP_MACOSX
   1.635 +  nsWeakFrame weakFrame(this);
   1.636 +  mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
   1.637 +  if (!weakFrame.IsAlive()) {
   1.638 +    return NS_ERROR_NOT_AVAILABLE;
   1.639 +  }
   1.640 +#endif
   1.641 +
   1.642 +  if (aCheckIsHidden && IsHidden())
   1.643 +    return NS_ERROR_FAILURE;
   1.644 +
   1.645 +  // refresh the plugin port as well
   1.646 +  window->window = mInstanceOwner->GetPluginPortFromWidget();
   1.647 +
   1.648 +  // Adjust plugin dimensions according to pixel snap results
   1.649 +  // and reduce amount of SetWindow calls
   1.650 +  nsPresContext* presContext = PresContext();
   1.651 +  nsRootPresContext* rootPC = presContext->GetRootPresContext();
   1.652 +  if (!rootPC)
   1.653 +    return NS_ERROR_FAILURE;
   1.654 +  int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
   1.655 +  nsIFrame* rootFrame = rootPC->PresShell()->FrameManager()->GetRootFrame();
   1.656 +  nsRect bounds = GetContentRectRelativeToSelf() + GetOffsetToCrossDoc(rootFrame);
   1.657 +  nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
   1.658 +
   1.659 +  // window must be in "display pixels"
   1.660 +  double scaleFactor = 1.0;
   1.661 +  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
   1.662 +    scaleFactor = 1.0;
   1.663 +  }
   1.664 +  size_t intScaleFactor = ceil(scaleFactor);
   1.665 +  window->x = intBounds.x / intScaleFactor;
   1.666 +  window->y = intBounds.y / intScaleFactor;
   1.667 +  window->width = intBounds.width / intScaleFactor;
   1.668 +  window->height = intBounds.height / intScaleFactor;
   1.669 +
   1.670 +  // Calling SetWindow might destroy this frame. We need to use the instance
   1.671 +  // owner to clean up so hold a ref.
   1.672 +  nsRefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner);
   1.673 +
   1.674 +  // This will call pi->SetWindow and take care of window subclassing
   1.675 +  // if needed, see bug 132759. Calling SetWindow can destroy this frame
   1.676 +  // so check for that before doing anything else with this frame's memory.
   1.677 +  if (mInstanceOwner->UseAsyncRendering()) {
   1.678 +    rv = pi->AsyncSetWindow(window);
   1.679 +  }
   1.680 +  else {
   1.681 +    rv = window->CallSetWindow(pi);
   1.682 +  }
   1.683 +
   1.684 +  instanceOwnerRef->ReleasePluginPort(window->window);
   1.685 +
   1.686 +  return rv;
   1.687 +}
   1.688 +
   1.689 +void
   1.690 +nsObjectFrame::RegisterPluginForGeometryUpdates()
   1.691 +{
   1.692 +  nsRootPresContext* rpc = PresContext()->GetRootPresContext();
   1.693 +  NS_ASSERTION(rpc, "We should have a root pres context!");
   1.694 +  if (mRootPresContextRegisteredWith == rpc || !rpc) {
   1.695 +    // Already registered with current root pres context,
   1.696 +    // or null root pres context...
   1.697 +    return;
   1.698 +  }
   1.699 +  if (mRootPresContextRegisteredWith && mRootPresContextRegisteredWith != rpc) {
   1.700 +    // Registered to some other root pres context. Unregister, and
   1.701 +    // re-register with our current one...
   1.702 +    UnregisterPluginForGeometryUpdates();
   1.703 +  }
   1.704 +  mRootPresContextRegisteredWith = rpc;
   1.705 +  mRootPresContextRegisteredWith->RegisterPluginForGeometryUpdates(mContent);
   1.706 +}
   1.707 +
   1.708 +void
   1.709 +nsObjectFrame::UnregisterPluginForGeometryUpdates()
   1.710 +{
   1.711 +  if (!mRootPresContextRegisteredWith) {
   1.712 +    // Not registered...
   1.713 +    return;
   1.714 +  }
   1.715 +  mRootPresContextRegisteredWith->UnregisterPluginForGeometryUpdates(mContent);
   1.716 +  mRootPresContextRegisteredWith = nullptr;
   1.717 +}
   1.718 +
   1.719 +void
   1.720 +nsObjectFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
   1.721 +{
   1.722 +  // The ownership model here is historically fuzzy. This should only be called
   1.723 +  // by nsPluginInstanceOwner when it is given a new frame, and
   1.724 +  // nsObjectLoadingContent should be arbitrating frame-ownership via its
   1.725 +  // HasNewFrame callback.
   1.726 +  mInstanceOwner = aOwner;
   1.727 +  if (mInstanceOwner) {
   1.728 +    return;
   1.729 +  }
   1.730 +  UnregisterPluginForGeometryUpdates();
   1.731 +  if (mWidget && mInnerView) {
   1.732 +    mInnerView->DetachWidgetEventHandler(mWidget);
   1.733 +    // Make sure the plugin is hidden in case an update of plugin geometry
   1.734 +    // hasn't happened since this plugin became hidden.
   1.735 +    nsIWidget* parent = mWidget->GetParent();
   1.736 +    if (parent) {
   1.737 +      nsTArray<nsIWidget::Configuration> configurations;
   1.738 +      nsIWidget::Configuration* configuration = configurations.AppendElement();
   1.739 +      configuration->mChild = mWidget;
   1.740 +      parent->ConfigureChildren(configurations);
   1.741 +
   1.742 +      mWidget->Show(false);
   1.743 +      mWidget->Enable(false);
   1.744 +      mWidget->SetParent(nullptr);
   1.745 +    }
   1.746 +  }
   1.747 +}
   1.748 +
   1.749 +bool
   1.750 +nsObjectFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
   1.751 +{
   1.752 +  if (aTabIndex)
   1.753 +    *aTabIndex = -1;
   1.754 +  return nsObjectFrameSuper::IsFocusable(aTabIndex, aWithMouse);
   1.755 +}
   1.756 +
   1.757 +bool
   1.758 +nsObjectFrame::IsHidden(bool aCheckVisibilityStyle) const
   1.759 +{
   1.760 +  if (aCheckVisibilityStyle) {
   1.761 +    if (!StyleVisibility()->IsVisibleOrCollapsed())
   1.762 +      return true;    
   1.763 +  }
   1.764 +
   1.765 +  // only <embed> tags support the HIDDEN attribute
   1.766 +  if (mContent->Tag() == nsGkAtoms::embed) {
   1.767 +    // Yes, these are really the kooky ways that you could tell 4.x
   1.768 +    // not to hide the <embed> once you'd put the 'hidden' attribute
   1.769 +    // on the tag...
   1.770 +
   1.771 +    // HIDDEN w/ no attributes gets translated as we are hidden for
   1.772 +    // compatibility w/ 4.x and IE so we don't create a non-painting
   1.773 +    // widget in layout. See bug 188959.
   1.774 +    nsAutoString hidden;
   1.775 +    if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::hidden, hidden) &&
   1.776 +       (hidden.IsEmpty() ||
   1.777 +        (!hidden.LowerCaseEqualsLiteral("false") &&
   1.778 +         !hidden.LowerCaseEqualsLiteral("no") &&
   1.779 +         !hidden.LowerCaseEqualsLiteral("off")))) {
   1.780 +      return true;
   1.781 +    }
   1.782 +  }
   1.783 +
   1.784 +  return false;
   1.785 +}
   1.786 +
   1.787 +nsIntPoint nsObjectFrame::GetWindowOriginInPixels(bool aWindowless)
   1.788 +{
   1.789 +  nsView * parentWithView;
   1.790 +  nsPoint origin(0,0);
   1.791 +
   1.792 +  GetOffsetFromView(origin, &parentWithView);
   1.793 +
   1.794 +  // if it's windowless, let's make sure we have our origin set right
   1.795 +  // it may need to be corrected, like after scrolling
   1.796 +  if (aWindowless && parentWithView) {
   1.797 +    nsPoint offsetToWidget;
   1.798 +    parentWithView->GetNearestWidget(&offsetToWidget);
   1.799 +    origin += offsetToWidget;
   1.800 +  }
   1.801 +  origin += GetContentRectRelativeToSelf().TopLeft();
   1.802 +
   1.803 +  return nsIntPoint(PresContext()->AppUnitsToDevPixels(origin.x),
   1.804 +                    PresContext()->AppUnitsToDevPixels(origin.y));
   1.805 +}
   1.806 +
   1.807 +nsresult
   1.808 +nsObjectFrame::DidReflow(nsPresContext*            aPresContext,
   1.809 +                         const nsHTMLReflowState*  aReflowState,
   1.810 +                         nsDidReflowStatus         aStatus)
   1.811 +{
   1.812 +  // Do this check before calling the superclass, as that clears
   1.813 +  // NS_FRAME_FIRST_REFLOW
   1.814 +  if (aStatus == nsDidReflowStatus::FINISHED &&
   1.815 +      (GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
   1.816 +    nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
   1.817 +    NS_ASSERTION(objContent, "Why not an object loading content?");
   1.818 +    objContent->HasNewFrame(this);
   1.819 +  }
   1.820 +
   1.821 +  nsresult rv = nsObjectFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
   1.822 +
   1.823 +  // The view is created hidden; once we have reflowed it and it has been
   1.824 +  // positioned then we show it.
   1.825 +  if (aStatus != nsDidReflowStatus::FINISHED)
   1.826 +    return rv;
   1.827 +
   1.828 +  if (HasView()) {
   1.829 +    nsView* view = GetView();
   1.830 +    nsViewManager* vm = view->GetViewManager();
   1.831 +    if (vm)
   1.832 +      vm->SetViewVisibility(view, IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow);
   1.833 +  }
   1.834 +
   1.835 +  return rv;
   1.836 +}
   1.837 +
   1.838 +/* static */ void
   1.839 +nsObjectFrame::PaintPrintPlugin(nsIFrame* aFrame, nsRenderingContext* aCtx,
   1.840 +                                const nsRect& aDirtyRect, nsPoint aPt)
   1.841 +{
   1.842 +  nsPoint pt = aPt + aFrame->GetContentRectRelativeToSelf().TopLeft();
   1.843 +  nsRenderingContext::AutoPushTranslation translate(aCtx, pt);
   1.844 +  // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
   1.845 +  static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
   1.846 +}
   1.847 +
   1.848 +class nsDisplayPluginReadback : public nsDisplayItem {
   1.849 +public:
   1.850 +  nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
   1.851 +    : nsDisplayItem(aBuilder, aFrame)
   1.852 +  {
   1.853 +    MOZ_COUNT_CTOR(nsDisplayPluginReadback);
   1.854 +  }
   1.855 +#ifdef NS_BUILD_REFCNT_LOGGING
   1.856 +  virtual ~nsDisplayPluginReadback() {
   1.857 +    MOZ_COUNT_DTOR(nsDisplayPluginReadback);
   1.858 +  }
   1.859 +#endif
   1.860 +
   1.861 +  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
   1.862 +                           bool* aSnap) MOZ_OVERRIDE;
   1.863 +  virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
   1.864 +                                   nsRegion* aVisibleRegion,
   1.865 +                                   const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
   1.866 +
   1.867 +  NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK)
   1.868 +
   1.869 +  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
   1.870 +                                             LayerManager* aManager,
   1.871 +                                             const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
   1.872 +  {
   1.873 +    return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
   1.874 +  }
   1.875 +
   1.876 +  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
   1.877 +                                   LayerManager* aManager,
   1.878 +                                   const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
   1.879 +  {
   1.880 +    return LAYER_ACTIVE;
   1.881 +  }
   1.882 +};
   1.883 +
   1.884 +static nsRect
   1.885 +GetDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
   1.886 +{
   1.887 +  // XXX For slightly more accurate region computations we should pixel-snap this
   1.888 +  return aFrame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
   1.889 +}
   1.890 +
   1.891 +nsRect
   1.892 +nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   1.893 +{
   1.894 +  *aSnap = false;
   1.895 +  return GetDisplayItemBounds(aBuilder, this, mFrame);
   1.896 +}
   1.897 +
   1.898 +bool
   1.899 +nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
   1.900 +                                           nsRegion* aVisibleRegion,
   1.901 +                                           const nsRect& aAllowVisibleRegionExpansion)
   1.902 +{
   1.903 +  if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
   1.904 +                                        aAllowVisibleRegionExpansion))
   1.905 +    return false;
   1.906 +
   1.907 +  nsRect expand;
   1.908 +  bool snap;
   1.909 +  expand.IntersectRect(aAllowVisibleRegionExpansion, GetBounds(aBuilder, &snap));
   1.910 +  // *Add* our bounds to the visible region so that stuff underneath us is
   1.911 +  // likely to be made visible, so we can use it for a background! This is
   1.912 +  // a bit crazy since we normally only subtract from the visible region.
   1.913 +  aVisibleRegion->Or(*aVisibleRegion, expand);
   1.914 +  return true;
   1.915 +}
   1.916 +
   1.917 +#ifdef MOZ_WIDGET_ANDROID
   1.918 +
   1.919 +class nsDisplayPluginVideo : public nsDisplayItem {
   1.920 +public:
   1.921 +  nsDisplayPluginVideo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
   1.922 +    : nsDisplayItem(aBuilder, aFrame), mVideoInfo(aVideoInfo)
   1.923 +  {
   1.924 +    MOZ_COUNT_CTOR(nsDisplayPluginVideo);
   1.925 +  }
   1.926 +#ifdef NS_BUILD_REFCNT_LOGGING
   1.927 +  virtual ~nsDisplayPluginVideo() {
   1.928 +    MOZ_COUNT_DTOR(nsDisplayPluginVideo);
   1.929 +  }
   1.930 +#endif
   1.931 +
   1.932 +  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
   1.933 +                           bool* aSnap) MOZ_OVERRIDE;
   1.934 +  virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
   1.935 +                                   nsRegion* aVisibleRegion,
   1.936 +                                   const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
   1.937 +
   1.938 +  NS_DISPLAY_DECL_NAME("PluginVideo", TYPE_PLUGIN_VIDEO)
   1.939 +
   1.940 +  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
   1.941 +                                             LayerManager* aManager,
   1.942 +                                             const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
   1.943 +  {
   1.944 +    return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
   1.945 +  }
   1.946 +
   1.947 +  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
   1.948 +                                   LayerManager* aManager,
   1.949 +                                   const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
   1.950 +  {
   1.951 +    return LAYER_ACTIVE;
   1.952 +  }
   1.953 +
   1.954 +  nsNPAPIPluginInstance::VideoInfo* VideoInfo() { return mVideoInfo; }
   1.955 +
   1.956 +private:
   1.957 +  nsNPAPIPluginInstance::VideoInfo* mVideoInfo;
   1.958 +};
   1.959 +
   1.960 +nsRect
   1.961 +nsDisplayPluginVideo::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   1.962 +{
   1.963 +  *aSnap = false;
   1.964 +  return GetDisplayItemBounds(aBuilder, this, mFrame);
   1.965 +}
   1.966 +
   1.967 +bool
   1.968 +nsDisplayPluginVideo::ComputeVisibility(nsDisplayListBuilder* aBuilder,
   1.969 +                                           nsRegion* aVisibleRegion,
   1.970 +                                           const nsRect& aAllowVisibleRegionExpansion)
   1.971 +{
   1.972 +  return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
   1.973 +                                          aAllowVisibleRegionExpansion);
   1.974 +}
   1.975 +
   1.976 +#endif
   1.977 +
   1.978 +nsRect
   1.979 +nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
   1.980 +{
   1.981 +  *aSnap = true;
   1.982 +  return GetDisplayItemBounds(aBuilder, this, mFrame);
   1.983 +}
   1.984 +
   1.985 +void
   1.986 +nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
   1.987 +                       nsRenderingContext* aCtx)
   1.988 +{
   1.989 +  nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
   1.990 +  bool snap;
   1.991 +  f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder, &snap));
   1.992 +}
   1.993 +
   1.994 +bool
   1.995 +nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
   1.996 +                                   nsRegion* aVisibleRegion,
   1.997 +                                   const nsRect& aAllowVisibleRegionExpansion)
   1.998 +{
   1.999 +  if (aBuilder->IsForPluginGeometry()) {
  1.1000 +    nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
  1.1001 +    if (!aBuilder->IsInTransform() || f->IsPaintedByGecko()) {
  1.1002 +      // Since transforms induce reference frames, we don't need to worry
  1.1003 +      // about this method fluffing out due to non-rectilinear transforms.
  1.1004 +      nsRect rAncestor = nsLayoutUtils::TransformFrameRectToAncestor(f,
  1.1005 +          f->GetContentRectRelativeToSelf(), ReferenceFrame());
  1.1006 +      nscoord appUnitsPerDevPixel =
  1.1007 +        ReferenceFrame()->PresContext()->AppUnitsPerDevPixel();
  1.1008 +      f->mNextConfigurationBounds = rAncestor.ToNearestPixels(appUnitsPerDevPixel);
  1.1009 +
  1.1010 +      nsRegion visibleRegion;
  1.1011 +      visibleRegion.And(*aVisibleRegion, GetClippedBounds(aBuilder));
  1.1012 +      // Make visibleRegion relative to f
  1.1013 +      visibleRegion.MoveBy(-ToReferenceFrame());
  1.1014 +
  1.1015 +      f->mNextConfigurationClipRegion.Clear();
  1.1016 +      nsRegionRectIterator iter(visibleRegion);
  1.1017 +      for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
  1.1018 +        nsRect rAncestor =
  1.1019 +          nsLayoutUtils::TransformFrameRectToAncestor(f, *r, ReferenceFrame());
  1.1020 +        nsIntRect rPixels = rAncestor.ToNearestPixels(appUnitsPerDevPixel)
  1.1021 +            - f->mNextConfigurationBounds.TopLeft();
  1.1022 +        if (!rPixels.IsEmpty()) {
  1.1023 +          f->mNextConfigurationClipRegion.AppendElement(rPixels);
  1.1024 +        }
  1.1025 +      }
  1.1026 +    }
  1.1027 +
  1.1028 +    if (f->mInnerView) {
  1.1029 +      // This should produce basically the same rectangle (but not relative
  1.1030 +      // to the root frame). We only call this here for the side-effect of
  1.1031 +      // setting mViewToWidgetOffset on the view.
  1.1032 +      f->mInnerView->CalcWidgetBounds(eWindowType_plugin);
  1.1033 +    }
  1.1034 +  }
  1.1035 +
  1.1036 +  return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
  1.1037 +                                          aAllowVisibleRegionExpansion);
  1.1038 +}
  1.1039 +
  1.1040 +nsRegion
  1.1041 +nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
  1.1042 +                                 bool* aSnap)
  1.1043 +{
  1.1044 +  *aSnap = false;
  1.1045 +  nsRegion result;
  1.1046 +  nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
  1.1047 +  if (!aBuilder->IsForPluginGeometry()) {
  1.1048 +    nsIWidget* widget = f->GetWidget();
  1.1049 +    if (widget) {
  1.1050 +      // Be conservative and treat plugins with widgets as not opaque,
  1.1051 +      // because that's simple and we might need the content under the widget
  1.1052 +      // if the widget is unexpectedly clipped away. (As can happen when
  1.1053 +      // chrome content over a plugin forces us to clip out the plugin for
  1.1054 +      // security reasons.)
  1.1055 +      // We shouldn't be repainting the content under plugins much anyway
  1.1056 +      // since there generally shouldn't be anything to invalidate or paint
  1.1057 +      // in ThebesLayers there.
  1.1058 +  	  return result;
  1.1059 +    }
  1.1060 +  }
  1.1061 +
  1.1062 +  if (f->IsOpaque()) {
  1.1063 +    nsRect bounds = GetBounds(aBuilder, aSnap);
  1.1064 +    if (aBuilder->IsForPluginGeometry() ||
  1.1065 +        (f->GetPaintedRect(this) + ToReferenceFrame()).Contains(bounds)) {
  1.1066 +      // We can treat this as opaque
  1.1067 +      result = bounds;
  1.1068 +    }
  1.1069 +  }
  1.1070 +
  1.1071 +  return result;
  1.1072 +}
  1.1073 +
  1.1074 +nsresult
  1.1075 +nsObjectFrame::PluginEventNotifier::Run() {
  1.1076 +  nsCOMPtr<nsIObserverService> obsSvc =
  1.1077 +    mozilla::services::GetObserverService();
  1.1078 +  obsSvc->NotifyObservers(nullptr, "plugin-changed-event", mEventType.get());
  1.1079 +  return NS_OK;
  1.1080 +}
  1.1081 +
  1.1082 +void
  1.1083 +nsObjectFrame::NotifyPluginReflowObservers()
  1.1084 +{
  1.1085 +  nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
  1.1086 +}
  1.1087 +
  1.1088 +void
  1.1089 +nsObjectFrame::DidSetWidgetGeometry()
  1.1090 +{
  1.1091 +#if defined(XP_MACOSX)
  1.1092 +  if (mInstanceOwner) {
  1.1093 +    mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
  1.1094 +  }
  1.1095 +#else
  1.1096 +  if (!mWidget && mInstanceOwner) {
  1.1097 +    // UpdateWindowVisibility will notify the plugin of position changes
  1.1098 +    // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
  1.1099 +    // We treat windowless plugins inside popups as always visible, since
  1.1100 +    // plugins inside popups don't get valid mNextConfigurationBounds
  1.1101 +    // set up.
  1.1102 +    mInstanceOwner->UpdateWindowVisibility(
  1.1103 +      nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
  1.1104 +      !mNextConfigurationBounds.IsEmpty());
  1.1105 +  }
  1.1106 +#endif
  1.1107 +}
  1.1108 +
  1.1109 +bool
  1.1110 +nsObjectFrame::IsOpaque() const
  1.1111 +{
  1.1112 +#if defined(XP_MACOSX)
  1.1113 +  // ???
  1.1114 +  return false;
  1.1115 +#elif defined(MOZ_WIDGET_ANDROID)
  1.1116 +  // We don't know, so just assume transparent
  1.1117 +  return false;
  1.1118 +#else
  1.1119 +  return !IsTransparentMode();
  1.1120 +#endif
  1.1121 +}
  1.1122 +
  1.1123 +bool
  1.1124 +nsObjectFrame::IsTransparentMode() const
  1.1125 +{
  1.1126 +#if defined(XP_MACOSX)
  1.1127 +  // ???
  1.1128 +  return false;
  1.1129 +#else
  1.1130 +  if (!mInstanceOwner)
  1.1131 +    return false;
  1.1132 +
  1.1133 +  NPWindow *window = nullptr;
  1.1134 +  mInstanceOwner->GetWindow(window);
  1.1135 +  if (!window) {
  1.1136 +    return false;
  1.1137 +  }
  1.1138 +
  1.1139 +  if (window->type != NPWindowTypeDrawable)
  1.1140 +    return false;
  1.1141 +
  1.1142 +  nsresult rv;
  1.1143 +  nsRefPtr<nsNPAPIPluginInstance> pi;
  1.1144 +  rv = mInstanceOwner->GetInstance(getter_AddRefs(pi));
  1.1145 +  if (NS_FAILED(rv) || !pi)
  1.1146 +    return false;
  1.1147 +
  1.1148 +  bool transparent = false;
  1.1149 +  pi->IsTransparent(&transparent);
  1.1150 +  return transparent;
  1.1151 +#endif
  1.1152 +}
  1.1153 +
  1.1154 +void
  1.1155 +nsObjectFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
  1.1156 +                                const nsRect&           aDirtyRect,
  1.1157 +                                const nsDisplayListSet& aLists)
  1.1158 +{
  1.1159 +  // XXX why are we painting collapsed object frames?
  1.1160 +  if (!IsVisibleOrCollapsedForPainting(aBuilder))
  1.1161 +    return;
  1.1162 +
  1.1163 +  DisplayBorderBackgroundOutline(aBuilder, aLists);
  1.1164 +
  1.1165 +  nsPresContext::nsPresContextType type = PresContext()->Type();
  1.1166 +
  1.1167 +  // If we are painting in Print Preview do nothing....
  1.1168 +  if (type == nsPresContext::eContext_PrintPreview)
  1.1169 +    return;
  1.1170 +
  1.1171 +  DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame");
  1.1172 +
  1.1173 +#ifndef XP_MACOSX
  1.1174 +  if (mWidget && aBuilder->IsInTransform()) {
  1.1175 +    // Windowed plugins should not be rendered inside a transform.
  1.1176 +    return;
  1.1177 +  }
  1.1178 +#endif
  1.1179 +
  1.1180 +  if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
  1.1181 +    NPWindow* window = nullptr;
  1.1182 +    mInstanceOwner->GetWindow(window);
  1.1183 +    bool isVisible = window && window->width > 0 && window->height > 0;
  1.1184 +    if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
  1.1185 +  #ifndef XP_MACOSX
  1.1186 +      mInstanceOwner->UpdateWindowVisibility(true);
  1.1187 +  #endif
  1.1188 +    }
  1.1189 +
  1.1190 +    mInstanceOwner->NotifyPaintWaiter(aBuilder);
  1.1191 +  }
  1.1192 +
  1.1193 +  DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
  1.1194 +    clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT);
  1.1195 +
  1.1196 +  // determine if we are printing
  1.1197 +  if (type == nsPresContext::eContext_Print) {
  1.1198 +    aLists.Content()->AppendNewToTop(new (aBuilder)
  1.1199 +      nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
  1.1200 +                       nsDisplayItem::TYPE_PRINT_PLUGIN));
  1.1201 +  } else {
  1.1202 +    LayerState state = GetLayerState(aBuilder, nullptr);
  1.1203 +    if (state == LAYER_INACTIVE &&
  1.1204 +        nsDisplayItem::ForceActiveLayers()) {
  1.1205 +      state = LAYER_ACTIVE;
  1.1206 +    }
  1.1207 +    // We don't need this on Android, and it just confuses things
  1.1208 +#if !MOZ_WIDGET_ANDROID
  1.1209 +    if (aBuilder->IsPaintingToWindow() &&
  1.1210 +        state == LAYER_ACTIVE &&
  1.1211 +        IsTransparentMode()) {
  1.1212 +      aLists.Content()->AppendNewToTop(new (aBuilder)
  1.1213 +        nsDisplayPluginReadback(aBuilder, this));
  1.1214 +    }
  1.1215 +#endif
  1.1216 +
  1.1217 +#if MOZ_WIDGET_ANDROID
  1.1218 +    if (aBuilder->IsPaintingToWindow() &&
  1.1219 +        state == LAYER_ACTIVE) {
  1.1220 +
  1.1221 +      nsTArray<nsNPAPIPluginInstance::VideoInfo*> videos;
  1.1222 +      mInstanceOwner->GetVideos(videos);
  1.1223 +
  1.1224 +      for (uint32_t i = 0; i < videos.Length(); i++) {
  1.1225 +        aLists.Content()->AppendNewToTop(new (aBuilder)
  1.1226 +          nsDisplayPluginVideo(aBuilder, this, videos[i]));
  1.1227 +      }
  1.1228 +    }
  1.1229 +#endif
  1.1230 +
  1.1231 +    aLists.Content()->AppendNewToTop(new (aBuilder)
  1.1232 +      nsDisplayPlugin(aBuilder, this));
  1.1233 +  }
  1.1234 +}
  1.1235 +
  1.1236 +void
  1.1237 +nsObjectFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
  1.1238 +                           const nsRect& aDirtyRect)
  1.1239 +{
  1.1240 +  nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent));
  1.1241 +  if (!obj)
  1.1242 +    return;
  1.1243 +
  1.1244 +  nsIFrame* frame = nullptr;
  1.1245 +  obj->GetPrintFrame(&frame);
  1.1246 +  if (!frame)
  1.1247 +    return;
  1.1248 +
  1.1249 +  nsPresContext* presContext = PresContext();
  1.1250 +  // make sure this is REALLY an nsIObjectFrame
  1.1251 +  // we may need to go through the children to get it
  1.1252 +  nsIObjectFrame* objectFrame = do_QueryFrame(frame);
  1.1253 +  if (!objectFrame)
  1.1254 +    objectFrame = GetNextObjectFrame(presContext,frame);
  1.1255 +  if (!objectFrame)
  1.1256 +    return;
  1.1257 +
  1.1258 +  // finally we can get our plugin instance
  1.1259 +  nsRefPtr<nsNPAPIPluginInstance> pi;
  1.1260 +  if (NS_FAILED(objectFrame->GetPluginInstance(getter_AddRefs(pi))) || !pi)
  1.1261 +    return;
  1.1262 +
  1.1263 +  // now we need to setup the correct location for printing
  1.1264 +  NPWindow window;
  1.1265 +  window.window = nullptr;
  1.1266 +
  1.1267 +  // prepare embedded mode printing struct
  1.1268 +  NPPrint npprint;
  1.1269 +  npprint.mode = NP_EMBED;
  1.1270 +
  1.1271 +  // we need to find out if we are windowless or not
  1.1272 +  bool windowless = false;
  1.1273 +  pi->IsWindowless(&windowless);
  1.1274 +  window.type = windowless ? NPWindowTypeDrawable : NPWindowTypeWindow;
  1.1275 +
  1.1276 +  window.clipRect.bottom = 0; window.clipRect.top = 0;
  1.1277 +  window.clipRect.left = 0; window.clipRect.right = 0;
  1.1278 +
  1.1279 +// platform specific printing code
  1.1280 +#if defined(XP_MACOSX) && !defined(__LP64__)
  1.1281 +#pragma clang diagnostic ignored "-Wdeprecated-declarations"
  1.1282 +  // Don't use this code if any of the QuickDraw APIs it currently requires
  1.1283 +  // are missing (as they probably will be on OS X 10.8 and up).
  1.1284 +  if (!&::SetRect || !&::NewGWorldFromPtr || !&::DisposeGWorld) {
  1.1285 +    NS_WARNING("Cannot print plugin -- required QuickDraw APIs are missing!");
  1.1286 +    return;
  1.1287 +  }
  1.1288 +
  1.1289 +  nsSize contentSize = GetContentRectRelativeToSelf().Size();
  1.1290 +  window.x = 0;
  1.1291 +  window.y = 0;
  1.1292 +  window.width = presContext->AppUnitsToDevPixels(contentSize.width);
  1.1293 +  window.height = presContext->AppUnitsToDevPixels(contentSize.height);
  1.1294 +
  1.1295 +  gfxContext *ctx = aRenderingContext.ThebesContext();
  1.1296 +  if (!ctx)
  1.1297 +    return;
  1.1298 +  gfxContextAutoSaveRestore save(ctx);
  1.1299 +
  1.1300 +  ctx->NewPath();
  1.1301 +
  1.1302 +  gfxRect rect(window.x, window.y, window.width, window.height);
  1.1303 +
  1.1304 +  ctx->Rectangle(rect);
  1.1305 +  ctx->Clip();
  1.1306 +
  1.1307 +  gfxQuartzNativeDrawing nativeDraw(ctx, rect);
  1.1308 +  CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
  1.1309 +  if (!cgContext) {
  1.1310 +    nativeDraw.EndNativeDrawing();
  1.1311 +    return;
  1.1312 +  }
  1.1313 +
  1.1314 +  window.clipRect.right = window.width;
  1.1315 +  window.clipRect.bottom = window.height;
  1.1316 +  window.type = NPWindowTypeDrawable;
  1.1317 +
  1.1318 +  ::Rect gwBounds;
  1.1319 +  ::SetRect(&gwBounds, 0, 0, window.width, window.height);
  1.1320 +
  1.1321 +  nsTArray<char> buffer(window.width * window.height * 4);
  1.1322 +  CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
  1.1323 +  if (!cspace) {
  1.1324 +    nativeDraw.EndNativeDrawing();
  1.1325 +    return;
  1.1326 +  }
  1.1327 +  CGContextRef cgBuffer =
  1.1328 +    ::CGBitmapContextCreate(buffer.Elements(), 
  1.1329 +                            window.width, window.height, 8, window.width * 4,
  1.1330 +                            cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst);
  1.1331 +  ::CGColorSpaceRelease(cspace);
  1.1332 +  if (!cgBuffer) {
  1.1333 +    nativeDraw.EndNativeDrawing();
  1.1334 +    return;
  1.1335 +  }
  1.1336 +  GWorldPtr gWorld;
  1.1337 +  if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds,
  1.1338 +                         nullptr, nullptr, 0,
  1.1339 +                         buffer.Elements(), window.width * 4) != noErr) {
  1.1340 +    ::CGContextRelease(cgBuffer);
  1.1341 +    nativeDraw.EndNativeDrawing();
  1.1342 +    return;
  1.1343 +  }
  1.1344 +
  1.1345 +  window.clipRect.right = window.width;
  1.1346 +  window.clipRect.bottom = window.height;
  1.1347 +  window.type = NPWindowTypeDrawable;
  1.1348 +  // Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
  1.1349 +  // &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
  1.1350 +  // GWorldPtr isn't any kind of standard (it's not documented anywhere).
  1.1351 +  // But that's what WebKit does.  And it's what the Flash plugin (apparently
  1.1352 +  // the only NPAPI plugin on OS X to support printing) seems to expect.  So
  1.1353 +  // we do the same.  The Flash plugin uses the CoreGraphics drawing mode.
  1.1354 +  // But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
  1.1355 +  // drawing mode.  See bug 191046.
  1.1356 +  window.window = &gWorld;
  1.1357 +  npprint.print.embedPrint.platformPrint = gWorld;
  1.1358 +  npprint.print.embedPrint.window = window;
  1.1359 +  pi->Print(&npprint);
  1.1360 +
  1.1361 +  ::CGContextTranslateCTM(cgContext, 0.0f, float(window.height));
  1.1362 +  ::CGContextScaleCTM(cgContext, 1.0f, -1.0f);
  1.1363 +  CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer);
  1.1364 +  if (!image) {
  1.1365 +    ::CGContextRestoreGState(cgContext);
  1.1366 +    ::CGContextRelease(cgBuffer);
  1.1367 +    ::DisposeGWorld(gWorld);
  1.1368 +    nativeDraw.EndNativeDrawing();
  1.1369 +    return;
  1.1370 +  }
  1.1371 +  ::CGContextDrawImage(cgContext,
  1.1372 +                       ::CGRectMake(0, 0, window.width, window.height),
  1.1373 +                       image);
  1.1374 +  ::CGImageRelease(image);
  1.1375 +  ::CGContextRelease(cgBuffer);
  1.1376 +
  1.1377 +  ::DisposeGWorld(gWorld);
  1.1378 +
  1.1379 +  nativeDraw.EndNativeDrawing();
  1.1380 +#pragma clang diagnostic warning "-Wdeprecated-declarations"
  1.1381 +#elif defined(XP_UNIX)
  1.1382 +
  1.1383 +  /* XXX this just flat-out doesn't work in a thebes world --
  1.1384 +   * RenderEPS is a no-op.  So don't bother to do any work here.
  1.1385 +   */
  1.1386 +  (void)window;
  1.1387 +  (void)npprint;
  1.1388 +
  1.1389 +#elif defined(XP_WIN)
  1.1390 +
  1.1391 +  /* On Windows, we use the win32 printing surface to print.  This, in
  1.1392 +   * turn, uses the Cairo paginated surface, which in turn uses the
  1.1393 +   * meta surface to record all operations and then play them back.
  1.1394 +   * This doesn't work too well for plugins, because if plugins render
  1.1395 +   * directly into the DC, the meta surface won't have any knowledge
  1.1396 +   * of them, and so at the end when it actually does the replay step,
  1.1397 +   * it'll fill the background with white and draw over whatever was
  1.1398 +   * rendered before.
  1.1399 +   *
  1.1400 +   * So, to avoid this, we use PushGroup, which creates a new windows
  1.1401 +   * surface, the plugin renders to that, and then we use normal
  1.1402 +   * cairo methods to composite that in such that it's recorded using the
  1.1403 +   * meta surface.
  1.1404 +   */
  1.1405 +
  1.1406 +  /* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
  1.1407 +  nsSize contentSize = GetContentRectRelativeToSelf().Size();
  1.1408 +  window.x = 0;
  1.1409 +  window.y = 0;
  1.1410 +  window.width = presContext->AppUnitsToDevPixels(contentSize.width);
  1.1411 +  window.height = presContext->AppUnitsToDevPixels(contentSize.height);
  1.1412 +
  1.1413 +  gfxContext *ctx = aRenderingContext.ThebesContext();
  1.1414 +
  1.1415 +  ctx->Save();
  1.1416 +
  1.1417 +  /* Make sure plugins don't do any damage outside of where they're supposed to */
  1.1418 +  ctx->NewPath();
  1.1419 +  gfxRect r(window.x, window.y, window.width, window.height);
  1.1420 +  ctx->Rectangle(r);
  1.1421 +  ctx->Clip();
  1.1422 +
  1.1423 +  gfxWindowsNativeDrawing nativeDraw(ctx, r);
  1.1424 +  do {
  1.1425 +    HDC dc = nativeDraw.BeginNativeDrawing();
  1.1426 +    if (!dc)
  1.1427 +      return;
  1.1428 +
  1.1429 +    // XXX don't we need to call nativeDraw.TransformToNativeRect here?
  1.1430 +    npprint.print.embedPrint.platformPrint = dc;
  1.1431 +    npprint.print.embedPrint.window = window;
  1.1432 +    // send off print info to plugin
  1.1433 +    pi->Print(&npprint);
  1.1434 +
  1.1435 +    nativeDraw.EndNativeDrawing();
  1.1436 +  } while (nativeDraw.ShouldRenderAgain());
  1.1437 +  nativeDraw.PaintToContext();
  1.1438 +
  1.1439 +  ctx->Restore();
  1.1440 +#endif
  1.1441 +
  1.1442 +  // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
  1.1443 +  // XXX Calling DidReflow here makes no sense!!!
  1.1444 +  nsDidReflowStatus status = nsDidReflowStatus::FINISHED; // should we use a special status?
  1.1445 +  frame->DidReflow(presContext,
  1.1446 +                   nullptr, status);  // DidReflow will take care of it
  1.1447 +}
  1.1448 +
  1.1449 +nsRect
  1.1450 +nsObjectFrame::GetPaintedRect(nsDisplayPlugin* aItem)
  1.1451 +{
  1.1452 +  if (!mInstanceOwner)
  1.1453 +    return nsRect();
  1.1454 +  nsRect r = GetContentRectRelativeToSelf();
  1.1455 +  if (!mInstanceOwner->UseAsyncRendering())
  1.1456 +    return r;
  1.1457 +
  1.1458 +  nsIntSize size = mInstanceOwner->GetCurrentImageSize();
  1.1459 +  nsPresContext* pc = PresContext();
  1.1460 +  r.IntersectRect(r, nsRect(0, 0, pc->DevPixelsToAppUnits(size.width),
  1.1461 +                                  pc->DevPixelsToAppUnits(size.height)));
  1.1462 +  return r;
  1.1463 +}
  1.1464 +
  1.1465 +LayerState
  1.1466 +nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
  1.1467 +                             LayerManager* aManager)
  1.1468 +{
  1.1469 +  if (!mInstanceOwner)
  1.1470 +    return LAYER_NONE;
  1.1471 +
  1.1472 +#ifdef MOZ_WIDGET_ANDROID
  1.1473 +  // We always want a layer on Honeycomb and later
  1.1474 +  if (AndroidBridge::Bridge()->GetAPIVersion() >= 11)
  1.1475 +    return LAYER_ACTIVE;
  1.1476 +#endif
  1.1477 +
  1.1478 +  if (!mInstanceOwner->UseAsyncRendering()) {
  1.1479 +    return LAYER_NONE;
  1.1480 +  }
  1.1481 +
  1.1482 +  return LAYER_ACTIVE;
  1.1483 +}
  1.1484 +
  1.1485 +already_AddRefed<Layer>
  1.1486 +nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
  1.1487 +                          LayerManager* aManager,
  1.1488 +                          nsDisplayItem* aItem,
  1.1489 +                          const ContainerLayerParameters& aContainerParameters)
  1.1490 +{
  1.1491 +  if (!mInstanceOwner)
  1.1492 +    return nullptr;
  1.1493 +
  1.1494 +  NPWindow* window = nullptr;
  1.1495 +  mInstanceOwner->GetWindow(window);
  1.1496 +  if (!window)
  1.1497 +    return nullptr;
  1.1498 +
  1.1499 +  if (window->width <= 0 || window->height <= 0)
  1.1500 +    return nullptr;
  1.1501 +
  1.1502 +  // window is in "display pixels", but size needs to be in device pixels
  1.1503 +  double scaleFactor = 1.0;
  1.1504 +  if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
  1.1505 +    scaleFactor = 1.0;
  1.1506 +  }
  1.1507 +  int intScaleFactor = ceil(scaleFactor);
  1.1508 +  IntSize size(window->width * intScaleFactor, window->height * intScaleFactor);
  1.1509 +
  1.1510 +  nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
  1.1511 +  gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
  1.1512 +  // to provide crisper and faster drawing.
  1.1513 +  r.Round();
  1.1514 +  nsRefPtr<Layer> layer =
  1.1515 +    (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
  1.1516 +
  1.1517 +  if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
  1.1518 +    // Create image
  1.1519 +    nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
  1.1520 +    if (!container) {
  1.1521 +      // This can occur if our instance is gone.
  1.1522 +      return nullptr;
  1.1523 +    }
  1.1524 +
  1.1525 +    if (!layer) {
  1.1526 +      mInstanceOwner->NotifyPaintWaiter(aBuilder);
  1.1527 +      // Initialize ImageLayer
  1.1528 +      layer = aManager->CreateImageLayer();
  1.1529 +      if (!layer)
  1.1530 +        return nullptr;
  1.1531 +    }
  1.1532 +
  1.1533 +    NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
  1.1534 +    ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
  1.1535 +#ifdef XP_MACOSX
  1.1536 +    if (!mInstanceOwner->UseAsyncRendering()) {
  1.1537 +      mInstanceOwner->DoCocoaEventDrawRect(r, nullptr);
  1.1538 +    }
  1.1539 +#endif
  1.1540 +
  1.1541 +    imglayer->SetScaleToSize(size, ScaleMode::STRETCH);
  1.1542 +    imglayer->SetContainer(container);
  1.1543 +    GraphicsFilter filter =
  1.1544 +      nsLayoutUtils::GetGraphicsFilterForFrame(this);
  1.1545 +#ifdef MOZ_GFX_OPTIMIZE_MOBILE
  1.1546 +    if (!aManager->IsCompositingCheap()) {
  1.1547 +      // Pixman just horrible with bilinear filter scaling
  1.1548 +      filter = GraphicsFilter::FILTER_NEAREST;
  1.1549 +    }
  1.1550 +#endif
  1.1551 +    imglayer->SetFilter(filter);
  1.1552 +
  1.1553 +    layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
  1.1554 +#ifdef MOZ_WIDGET_ANDROID
  1.1555 +  } else if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_VIDEO) {
  1.1556 +    nsDisplayPluginVideo* videoItem = reinterpret_cast<nsDisplayPluginVideo*>(aItem);
  1.1557 +    nsNPAPIPluginInstance::VideoInfo* videoInfo = videoItem->VideoInfo();
  1.1558 +
  1.1559 +    nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainerForVideo(videoInfo);
  1.1560 +    if (!container)
  1.1561 +      return nullptr;
  1.1562 +
  1.1563 +    if (!layer) {
  1.1564 +      // Initialize ImageLayer
  1.1565 +      layer = aManager->CreateImageLayer();
  1.1566 +      if (!layer)
  1.1567 +        return nullptr;
  1.1568 +    }
  1.1569 +
  1.1570 +    ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
  1.1571 +    imglayer->SetContainer(container);
  1.1572 +
  1.1573 +    layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
  1.1574 +
  1.1575 +    // Set the offset and size according to the video dimensions
  1.1576 +    r.MoveBy(videoInfo->mDimensions.TopLeft());
  1.1577 +    size.width = videoInfo->mDimensions.width;
  1.1578 +    size.height = videoInfo->mDimensions.height;
  1.1579 +#endif
  1.1580 +  } else {
  1.1581 +    NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
  1.1582 +                 "Unknown item type");
  1.1583 +    NS_ABORT_IF_FALSE(!IsOpaque(), "Opaque plugins don't use backgrounds");
  1.1584 +
  1.1585 +    if (!layer) {
  1.1586 +      layer = aManager->CreateReadbackLayer();
  1.1587 +      if (!layer)
  1.1588 +        return nullptr;
  1.1589 +    }
  1.1590 +    NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
  1.1591 +
  1.1592 +    ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
  1.1593 +    if (readback->GetSize() != ThebesIntSize(size)) {
  1.1594 +      // This will destroy any old background sink and notify us that the
  1.1595 +      // background is now unknown
  1.1596 +      readback->SetSink(nullptr);
  1.1597 +      readback->SetSize(ThebesIntSize(size));
  1.1598 +
  1.1599 +      if (mBackgroundSink) {
  1.1600 +        // Maybe we still have a background sink associated with another
  1.1601 +        // readback layer that wasn't recycled for some reason? Unhook it
  1.1602 +        // now so that if this frame goes away, it doesn't have a dangling
  1.1603 +        // reference to us.
  1.1604 +        mBackgroundSink->Destroy();
  1.1605 +      }
  1.1606 +      mBackgroundSink =
  1.1607 +        new PluginBackgroundSink(this,
  1.1608 +                                 readback->AllocateSequenceNumber());
  1.1609 +      readback->SetSink(mBackgroundSink);
  1.1610 +      // The layer has taken ownership of our sink. When either the sink dies
  1.1611 +      // or the frame dies, the connection from the surviving object is nulled out.
  1.1612 +    }
  1.1613 +  }
  1.1614 +
  1.1615 +  // Set a transform on the layer to draw the plugin in the right place
  1.1616 +  Matrix transform;
  1.1617 +  gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
  1.1618 +  transform.Translate(p.x, p.y);
  1.1619 +
  1.1620 +  layer->SetBaseTransform(Matrix4x4::From2D(transform));
  1.1621 +  layer->SetVisibleRegion(ThebesIntRect(IntRect(IntPoint(0, 0), size)));
  1.1622 +  return layer.forget();
  1.1623 +}
  1.1624 +
  1.1625 +void
  1.1626 +nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
  1.1627 +                           nsRenderingContext& aRenderingContext,
  1.1628 +                           const nsRect& aDirtyRect, const nsRect& aPluginRect)
  1.1629 +{
  1.1630 +#if defined(MOZ_WIDGET_ANDROID)
  1.1631 +  if (mInstanceOwner) {
  1.1632 +    gfxRect frameGfxRect =
  1.1633 +      PresContext()->AppUnitsToGfxUnits(aPluginRect);
  1.1634 +    gfxRect dirtyGfxRect =
  1.1635 +      PresContext()->AppUnitsToGfxUnits(aDirtyRect);
  1.1636 +
  1.1637 +    gfxContext* ctx = aRenderingContext.ThebesContext();
  1.1638 +
  1.1639 +    mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
  1.1640 +    return;
  1.1641 +  }
  1.1642 +#endif
  1.1643 +
  1.1644 +  // Screen painting code
  1.1645 +#if defined(XP_MACOSX)
  1.1646 +  // delegate all painting to the plugin instance.
  1.1647 +  if (mInstanceOwner) {
  1.1648 +    if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics ||
  1.1649 +        mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
  1.1650 +        mInstanceOwner->GetDrawingModel() == 
  1.1651 +                                  NPDrawingModelInvalidatingCoreAnimation) {
  1.1652 +      int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
  1.1653 +      // Clip to the content area where the plugin should be drawn. If
  1.1654 +      // we don't do this, the plugin can draw outside its bounds.
  1.1655 +      nsIntRect contentPixels = aPluginRect.ToNearestPixels(appUnitsPerDevPixel);
  1.1656 +      nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel);
  1.1657 +      nsIntRect clipPixels;
  1.1658 +      clipPixels.IntersectRect(contentPixels, dirtyPixels);
  1.1659 +
  1.1660 +      // Don't invoke the drawing code if the clip is empty.
  1.1661 +      if (clipPixels.IsEmpty())
  1.1662 +        return;
  1.1663 +
  1.1664 +      gfxRect nativeClipRect(clipPixels.x, clipPixels.y,
  1.1665 +                             clipPixels.width, clipPixels.height);
  1.1666 +      gfxContext* ctx = aRenderingContext.ThebesContext();
  1.1667 +
  1.1668 +      gfxContextAutoSaveRestore save(ctx);
  1.1669 +      ctx->NewPath();
  1.1670 +      ctx->Rectangle(nativeClipRect);
  1.1671 +      ctx->Clip();
  1.1672 +      gfxPoint offset(contentPixels.x, contentPixels.y);
  1.1673 +      ctx->Translate(offset);
  1.1674 +
  1.1675 +      gfxQuartzNativeDrawing nativeDrawing(ctx, nativeClipRect - offset);
  1.1676 +
  1.1677 +      CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
  1.1678 +      if (!cgContext) {
  1.1679 +        NS_WARNING("null CGContextRef during PaintPlugin");
  1.1680 +        return;
  1.1681 +      }
  1.1682 +
  1.1683 +      nsRefPtr<nsNPAPIPluginInstance> inst;
  1.1684 +      GetPluginInstance(getter_AddRefs(inst));
  1.1685 +      if (!inst) {
  1.1686 +        NS_WARNING("null plugin instance during PaintPlugin");
  1.1687 +        nativeDrawing.EndNativeDrawing();
  1.1688 +        return;
  1.1689 +      }
  1.1690 +      NPWindow* window;
  1.1691 +      mInstanceOwner->GetWindow(window);
  1.1692 +      if (!window) {
  1.1693 +        NS_WARNING("null plugin window during PaintPlugin");
  1.1694 +        nativeDrawing.EndNativeDrawing();
  1.1695 +        return;
  1.1696 +      }
  1.1697 +      NP_CGContext* cgPluginPortCopy =
  1.1698 +                static_cast<NP_CGContext*>(mInstanceOwner->GetPluginPortCopy());
  1.1699 +      if (!cgPluginPortCopy) {
  1.1700 +        NS_WARNING("null plugin port copy during PaintPlugin");
  1.1701 +        nativeDrawing.EndNativeDrawing();
  1.1702 +        return;
  1.1703 +      }
  1.1704 +
  1.1705 +      mInstanceOwner->BeginCGPaint();
  1.1706 +      if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
  1.1707 +          mInstanceOwner->GetDrawingModel() == 
  1.1708 +                                   NPDrawingModelInvalidatingCoreAnimation) {
  1.1709 +        // CoreAnimation is updated, render the layer and perform a readback.
  1.1710 +        mInstanceOwner->RenderCoreAnimation(cgContext, window->width, window->height);
  1.1711 +      } else {
  1.1712 +        mInstanceOwner->Paint(nativeClipRect - offset, cgContext);
  1.1713 +      }
  1.1714 +      mInstanceOwner->EndCGPaint();
  1.1715 +
  1.1716 +      nativeDrawing.EndNativeDrawing();
  1.1717 +    } else {
  1.1718 +      // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
  1.1719 +      nsRenderingContext::AutoPushTranslation
  1.1720 +        translate(&aRenderingContext, aPluginRect.TopLeft());
  1.1721 +
  1.1722 +      // this rect is used only in the CoreGraphics drawing model
  1.1723 +      gfxRect tmpRect(0, 0, 0, 0);
  1.1724 +      mInstanceOwner->Paint(tmpRect, nullptr);
  1.1725 +    }
  1.1726 +  }
  1.1727 +#elif defined(MOZ_X11)
  1.1728 +  if (mInstanceOwner) {
  1.1729 +    NPWindow *window;
  1.1730 +    mInstanceOwner->GetWindow(window);
  1.1731 +    if (window->type == NPWindowTypeDrawable) {
  1.1732 +      gfxRect frameGfxRect =
  1.1733 +        PresContext()->AppUnitsToGfxUnits(aPluginRect);
  1.1734 +      gfxRect dirtyGfxRect =
  1.1735 +        PresContext()->AppUnitsToGfxUnits(aDirtyRect);
  1.1736 +      gfxContext* ctx = aRenderingContext.ThebesContext();
  1.1737 +
  1.1738 +      mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
  1.1739 +    }
  1.1740 +  }
  1.1741 +#elif defined(XP_WIN)
  1.1742 +  nsRefPtr<nsNPAPIPluginInstance> inst;
  1.1743 +  GetPluginInstance(getter_AddRefs(inst));
  1.1744 +  if (inst) {
  1.1745 +    gfxRect frameGfxRect =
  1.1746 +      PresContext()->AppUnitsToGfxUnits(aPluginRect);
  1.1747 +    gfxRect dirtyGfxRect =
  1.1748 +      PresContext()->AppUnitsToGfxUnits(aDirtyRect);
  1.1749 +    gfxContext *ctx = aRenderingContext.ThebesContext();
  1.1750 +    gfxMatrix currentMatrix = ctx->CurrentMatrix();
  1.1751 +
  1.1752 +    if (ctx->UserToDevicePixelSnapped(frameGfxRect, false)) {
  1.1753 +      dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect);
  1.1754 +      ctx->IdentityMatrix();
  1.1755 +    }
  1.1756 +    dirtyGfxRect.RoundOut();
  1.1757 +
  1.1758 +    // Look if it's windowless
  1.1759 +    NPWindow *window;
  1.1760 +    mInstanceOwner->GetWindow(window);
  1.1761 +
  1.1762 +    if (window->type == NPWindowTypeDrawable) {
  1.1763 +      // the offset of the DC
  1.1764 +      nsPoint origin;
  1.1765 +
  1.1766 +      gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
  1.1767 +      if (nativeDraw.IsDoublePass()) {
  1.1768 +        // OOP plugin specific: let the shim know before we paint if we are doing a
  1.1769 +        // double pass render. If this plugin isn't oop, the register window message
  1.1770 +        // will be ignored.
  1.1771 +        NPEvent pluginEvent;
  1.1772 +        pluginEvent.event = plugins::DoublePassRenderingEvent();
  1.1773 +        pluginEvent.wParam = 0;
  1.1774 +        pluginEvent.lParam = 0;
  1.1775 +        if (pluginEvent.event)
  1.1776 +          inst->HandleEvent(&pluginEvent, nullptr);
  1.1777 +      }
  1.1778 +      do {
  1.1779 +        HDC hdc = nativeDraw.BeginNativeDrawing();
  1.1780 +        if (!hdc)
  1.1781 +          return;
  1.1782 +
  1.1783 +        RECT dest;
  1.1784 +        nativeDraw.TransformToNativeRect(frameGfxRect, dest);
  1.1785 +        RECT dirty;
  1.1786 +        nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty);
  1.1787 +
  1.1788 +        window->window = hdc;
  1.1789 +        window->x = dest.left;
  1.1790 +        window->y = dest.top;
  1.1791 +        window->clipRect.left = 0;
  1.1792 +        window->clipRect.top = 0;
  1.1793 +        // if we're painting, we're visible.
  1.1794 +        window->clipRect.right = window->width;
  1.1795 +        window->clipRect.bottom = window->height;
  1.1796 +
  1.1797 +        // Windowless plugins on windows need a special event to update their location,
  1.1798 +        // see bug 135737.
  1.1799 +        //
  1.1800 +        // bug 271442: note, the rectangle we send is now purely the bounds of the plugin
  1.1801 +        // relative to the window it is contained in, which is useful for the plugin to
  1.1802 +        // correctly translate mouse coordinates.
  1.1803 +        //
  1.1804 +        // this does not mesh with the comments for bug 135737 which imply that the rectangle
  1.1805 +        // must be clipped in some way to prevent the plugin attempting to paint over areas
  1.1806 +        // it shouldn't.
  1.1807 +        //
  1.1808 +        // since the two uses of the rectangle are mutually exclusive in some cases, and
  1.1809 +        // since I don't see any incorrect painting (at least with Flash and ViewPoint -
  1.1810 +        // the originator of bug 135737), it seems that windowless plugins are not relying
  1.1811 +        // on information here for clipping their drawing, and we can safely use this message
  1.1812 +        // to tell the plugin exactly where it is in all cases.
  1.1813 +
  1.1814 +        nsIntPoint origin = GetWindowOriginInPixels(true);
  1.1815 +        nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
  1.1816 +
  1.1817 +        if (!mWindowlessRect.IsEqualEdges(winlessRect)) {
  1.1818 +          mWindowlessRect = winlessRect;
  1.1819 +
  1.1820 +          WINDOWPOS winpos;
  1.1821 +          memset(&winpos, 0, sizeof(winpos));
  1.1822 +          winpos.x = mWindowlessRect.x;
  1.1823 +          winpos.y = mWindowlessRect.y;
  1.1824 +          winpos.cx = mWindowlessRect.width;
  1.1825 +          winpos.cy = mWindowlessRect.height;
  1.1826 +
  1.1827 +          // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
  1.1828 +          NPEvent pluginEvent;
  1.1829 +          pluginEvent.event = WM_WINDOWPOSCHANGED;
  1.1830 +          pluginEvent.wParam = 0;
  1.1831 +          pluginEvent.lParam = (LPARAM)&winpos;
  1.1832 +          inst->HandleEvent(&pluginEvent, nullptr);
  1.1833 +        }
  1.1834 +
  1.1835 +        inst->SetWindow(window);
  1.1836 +
  1.1837 +        mInstanceOwner->Paint(dirty, hdc);
  1.1838 +        nativeDraw.EndNativeDrawing();
  1.1839 +      } while (nativeDraw.ShouldRenderAgain());
  1.1840 +      nativeDraw.PaintToContext();
  1.1841 +    }
  1.1842 +
  1.1843 +    ctx->SetMatrix(currentMatrix);
  1.1844 +  }
  1.1845 +#endif
  1.1846 +}
  1.1847 +
  1.1848 +nsresult
  1.1849 +nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
  1.1850 +                           WidgetGUIEvent* anEvent,
  1.1851 +                           nsEventStatus* anEventStatus)
  1.1852 +{
  1.1853 +  NS_ENSURE_ARG_POINTER(anEvent);
  1.1854 +  NS_ENSURE_ARG_POINTER(anEventStatus);
  1.1855 +  nsresult rv = NS_OK;
  1.1856 +
  1.1857 +  if (!mInstanceOwner)
  1.1858 +    return NS_ERROR_NULL_POINTER;
  1.1859 +
  1.1860 +  mInstanceOwner->ConsiderNewEventloopNestingLevel();
  1.1861 +
  1.1862 +  if (anEvent->message == NS_PLUGIN_ACTIVATE) {
  1.1863 +    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
  1.1864 +    nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetContent());
  1.1865 +    if (fm && elem)
  1.1866 +      return fm->SetFocus(elem, 0);
  1.1867 +  }
  1.1868 +  else if (anEvent->message == NS_PLUGIN_FOCUS) {
  1.1869 +    nsIFocusManager* fm = nsFocusManager::GetFocusManager();
  1.1870 +    if (fm)
  1.1871 +      return fm->FocusPlugin(GetContent());
  1.1872 +  }
  1.1873 +
  1.1874 +#ifdef XP_MACOSX
  1.1875 +  if (anEvent->message == NS_PLUGIN_RESOLUTION_CHANGED) {
  1.1876 +    double scaleFactor = 1.0;
  1.1877 +    mInstanceOwner->GetContentsScaleFactor(&scaleFactor);
  1.1878 +    mInstanceOwner->ContentsScaleFactorChanged(scaleFactor);
  1.1879 +    return NS_OK;
  1.1880 +  }
  1.1881 +#endif
  1.1882 +
  1.1883 +  if (mInstanceOwner->SendNativeEvents() &&
  1.1884 +      anEvent->IsNativeEventDelivererForPlugin()) {
  1.1885 +    *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
  1.1886 +    // Due to plugin code reentering Gecko, this frame may be dead at this
  1.1887 +    // point.
  1.1888 +    return rv;
  1.1889 +  }
  1.1890 +
  1.1891 +#ifdef XP_WIN
  1.1892 +  rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
  1.1893 +  return rv;
  1.1894 +#endif
  1.1895 +
  1.1896 +#ifdef XP_MACOSX
  1.1897 +  // we want to process some native mouse events in the cocoa event model
  1.1898 +  if ((anEvent->message == NS_MOUSE_ENTER ||
  1.1899 +       anEvent->message == NS_WHEEL_WHEEL) &&
  1.1900 +      mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
  1.1901 +    *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
  1.1902 +    // Due to plugin code reentering Gecko, this frame may be dead at this
  1.1903 +    // point.
  1.1904 +    return rv;
  1.1905 +  }
  1.1906 +
  1.1907 +  // These two calls to nsIPresShell::SetCapturingContext() (on mouse-down
  1.1908 +  // and mouse-up) are needed to make the routing of mouse events while
  1.1909 +  // dragging conform to standard OS X practice, and to the Cocoa NPAPI spec.
  1.1910 +  // See bug 525078 and bug 909678.
  1.1911 +  if (anEvent->message == NS_MOUSE_BUTTON_DOWN) {
  1.1912 +    nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
  1.1913 +  }
  1.1914 +#endif
  1.1915 +
  1.1916 +  rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
  1.1917 +
  1.1918 +  // We need to be careful from this point because the call to
  1.1919 +  // nsObjectFrameSuper::HandleEvent() might have killed us.
  1.1920 +
  1.1921 +#ifdef XP_MACOSX
  1.1922 +  if (anEvent->message == NS_MOUSE_BUTTON_UP) {
  1.1923 +    nsIPresShell::SetCapturingContent(nullptr, 0);
  1.1924 +  }
  1.1925 +#endif
  1.1926 +
  1.1927 +  return rv;
  1.1928 +}
  1.1929 +
  1.1930 +nsresult
  1.1931 +nsObjectFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
  1.1932 +{
  1.1933 +  *aPluginInstance = nullptr;
  1.1934 +
  1.1935 +  if (!mInstanceOwner) {
  1.1936 +    return NS_OK;
  1.1937 +  }
  1.1938 +
  1.1939 +  return mInstanceOwner->GetInstance(aPluginInstance);
  1.1940 +}
  1.1941 +
  1.1942 +nsresult
  1.1943 +nsObjectFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
  1.1944 +{
  1.1945 +  if (!mInstanceOwner) {
  1.1946 +    return NS_ERROR_FAILURE;
  1.1947 +  }
  1.1948 +
  1.1949 +  nsRefPtr<nsNPAPIPluginInstance> inst;
  1.1950 +  mInstanceOwner->GetInstance(getter_AddRefs(inst));
  1.1951 +  if (!inst) {
  1.1952 +    return NS_ERROR_FAILURE;
  1.1953 +  }
  1.1954 +
  1.1955 +  bool useDOMCursor = static_cast<nsNPAPIPluginInstance*>(inst.get())->UsesDOMForCursor();
  1.1956 +  if (!useDOMCursor) {
  1.1957 +    return NS_ERROR_FAILURE;
  1.1958 +  }
  1.1959 +
  1.1960 +  return nsObjectFrameSuper::GetCursor(aPoint, aCursor);
  1.1961 +}
  1.1962 +
  1.1963 +void
  1.1964 +nsObjectFrame::SetIsDocumentActive(bool aIsActive)
  1.1965 +{
  1.1966 +#ifndef XP_MACOSX
  1.1967 +  if (mInstanceOwner) {
  1.1968 +    mInstanceOwner->UpdateDocumentActiveState(aIsActive);
  1.1969 +  }
  1.1970 +#endif
  1.1971 +}
  1.1972 +
  1.1973 +// static
  1.1974 +nsIObjectFrame *
  1.1975 +nsObjectFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
  1.1976 +{
  1.1977 +  nsIFrame* child = aRoot->GetFirstPrincipalChild();
  1.1978 +
  1.1979 +  while (child) {
  1.1980 +    nsIObjectFrame* outFrame = do_QueryFrame(child);
  1.1981 +    if (outFrame) {
  1.1982 +      nsRefPtr<nsNPAPIPluginInstance> pi;
  1.1983 +      outFrame->GetPluginInstance(getter_AddRefs(pi));  // make sure we have a REAL plugin
  1.1984 +      if (pi)
  1.1985 +        return outFrame;
  1.1986 +    }
  1.1987 +
  1.1988 +    outFrame = GetNextObjectFrame(aPresContext, child);
  1.1989 +    if (outFrame)
  1.1990 +      return outFrame;
  1.1991 +    child = child->GetNextSibling();
  1.1992 +  }
  1.1993 +
  1.1994 +  return nullptr;
  1.1995 +}
  1.1996 +
  1.1997 +/*static*/ void
  1.1998 +nsObjectFrame::BeginSwapDocShells(nsIContent* aContent, void*)
  1.1999 +{
  1.2000 +  NS_PRECONDITION(aContent, "");
  1.2001 +
  1.2002 +  // This function is called from a document content enumerator so we need
  1.2003 +  // to filter out the nsObjectFrames and ignore the rest.
  1.2004 +  nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame());
  1.2005 +  if (!obj)
  1.2006 +    return;
  1.2007 +
  1.2008 +  nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj);
  1.2009 +  NS_ASSERTION(!objectFrame->mWidget || objectFrame->mWidget->GetParent(),
  1.2010 +               "Plugin windows must not be toplevel");
  1.2011 +  objectFrame->UnregisterPluginForGeometryUpdates();
  1.2012 +}
  1.2013 +
  1.2014 +/*static*/ void
  1.2015 +nsObjectFrame::EndSwapDocShells(nsIContent* aContent, void*)
  1.2016 +{
  1.2017 +  NS_PRECONDITION(aContent, "");
  1.2018 +
  1.2019 +  // This function is called from a document content enumerator so we need
  1.2020 +  // to filter out the nsObjectFrames and ignore the rest.
  1.2021 +  nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame());
  1.2022 +  if (!obj)
  1.2023 +    return;
  1.2024 +
  1.2025 +  nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj);
  1.2026 +  nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext();
  1.2027 +  NS_ASSERTION(rootPC, "unable to register the plugin frame");
  1.2028 +  nsIWidget* widget = objectFrame->mWidget;
  1.2029 +  if (widget) {
  1.2030 +    // Reparent the widget.
  1.2031 +    nsIWidget* parent =
  1.2032 +      rootPC->PresShell()->GetRootFrame()->GetNearestWidget();
  1.2033 +    widget->SetParent(parent);
  1.2034 +    nsWeakFrame weakFrame(objectFrame);
  1.2035 +    objectFrame->CallSetWindow();
  1.2036 +    if (!weakFrame.IsAlive()) {
  1.2037 +      return;
  1.2038 +    }
  1.2039 +  }
  1.2040 +
  1.2041 +#ifdef XP_MACOSX
  1.2042 +  if (objectFrame->mWidget) {
  1.2043 +    objectFrame->RegisterPluginForGeometryUpdates();
  1.2044 +  }
  1.2045 +#else
  1.2046 +  objectFrame->RegisterPluginForGeometryUpdates();
  1.2047 +#endif
  1.2048 +}
  1.2049 +
  1.2050 +nsIFrame*
  1.2051 +NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  1.2052 +{
  1.2053 +  return new (aPresShell) nsObjectFrame(aContext);
  1.2054 +}
  1.2055 +
  1.2056 +bool
  1.2057 +nsObjectFrame::IsPaintedByGecko() const
  1.2058 +{
  1.2059 +#ifdef XP_MACOSX
  1.2060 +  return true;
  1.2061 +#else
  1.2062 +  return !mWidget;
  1.2063 +#endif
  1.2064 +}
  1.2065 +
  1.2066 +NS_IMPL_FRAMEARENA_HELPERS(nsObjectFrame)

mercurial