layout/generic/nsObjectFrame.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 // vim:set ts=2 sts=2 sw=2 et cin:
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /* rendering objects for replaced elements implemented by a plugin */
michael@0 8
michael@0 9 #include "nsObjectFrame.h"
michael@0 10
michael@0 11 #include "gfx2DGlue.h"
michael@0 12 #include "mozilla/BasicEvents.h"
michael@0 13 #ifdef XP_WIN
michael@0 14 // This is needed for DoublePassRenderingEvent.
michael@0 15 #include "mozilla/plugins/PluginMessageUtils.h"
michael@0 16 #endif
michael@0 17
michael@0 18 #include "nscore.h"
michael@0 19 #include "nsCOMPtr.h"
michael@0 20 #include "nsPresContext.h"
michael@0 21 #include "nsIPresShell.h"
michael@0 22 #include "nsWidgetsCID.h"
michael@0 23 #include "nsView.h"
michael@0 24 #include "nsViewManager.h"
michael@0 25 #include "nsString.h"
michael@0 26 #include "nsGkAtoms.h"
michael@0 27 #include "nsIPluginInstanceOwner.h"
michael@0 28 #include "nsNPAPIPluginInstance.h"
michael@0 29 #include "nsIDOMElement.h"
michael@0 30 #include "nsRenderingContext.h"
michael@0 31 #include "npapi.h"
michael@0 32 #include "nsIObjectLoadingContent.h"
michael@0 33 #include "nsContentUtils.h"
michael@0 34 #include "nsDisplayList.h"
michael@0 35 #include "nsFocusManager.h"
michael@0 36 #include "nsLayoutUtils.h"
michael@0 37 #include "nsFrameManager.h"
michael@0 38 #include "nsIObserverService.h"
michael@0 39 #include "GeckoProfiler.h"
michael@0 40 #include <algorithm>
michael@0 41
michael@0 42 #include "nsIObjectFrame.h"
michael@0 43 #include "nsPluginNativeWindow.h"
michael@0 44 #include "FrameLayerBuilder.h"
michael@0 45
michael@0 46 #include "ImageLayers.h"
michael@0 47 #include "nsPluginInstanceOwner.h"
michael@0 48
michael@0 49 #ifdef XP_WIN
michael@0 50 #include "gfxWindowsNativeDrawing.h"
michael@0 51 #include "gfxWindowsSurface.h"
michael@0 52 #endif
michael@0 53
michael@0 54 #include "Layers.h"
michael@0 55 #include "ReadbackLayer.h"
michael@0 56 #include "ImageContainer.h"
michael@0 57
michael@0 58 // accessibility support
michael@0 59 #ifdef ACCESSIBILITY
michael@0 60 #include "nsAccessibilityService.h"
michael@0 61 #endif
michael@0 62
michael@0 63 #ifdef MOZ_LOGGING
michael@0 64 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
michael@0 65 #endif /* MOZ_LOGGING */
michael@0 66 #include "prlog.h"
michael@0 67
michael@0 68 #ifdef XP_MACOSX
michael@0 69 #include "gfxQuartzNativeDrawing.h"
michael@0 70 #include "nsPluginUtilsOSX.h"
michael@0 71 #include "mozilla/gfx/QuartzSupport.h"
michael@0 72 #endif
michael@0 73
michael@0 74 #ifdef MOZ_X11
michael@0 75 #include "mozilla/X11Util.h"
michael@0 76 using mozilla::DefaultXDisplay;
michael@0 77 #endif
michael@0 78
michael@0 79 #ifdef XP_WIN
michael@0 80 #include <wtypes.h>
michael@0 81 #include <winuser.h>
michael@0 82 #endif
michael@0 83
michael@0 84 #ifdef MOZ_WIDGET_ANDROID
michael@0 85 #include "AndroidBridge.h"
michael@0 86 #include "GLContext.h"
michael@0 87 #endif
michael@0 88
michael@0 89 #ifdef CreateEvent // Thank you MS.
michael@0 90 #undef CreateEvent
michael@0 91 #endif
michael@0 92
michael@0 93 #ifdef PR_LOGGING
michael@0 94 static PRLogModuleInfo *
michael@0 95 GetObjectFrameLog()
michael@0 96 {
michael@0 97 static PRLogModuleInfo *sLog;
michael@0 98 if (!sLog)
michael@0 99 sLog = PR_NewLogModule("nsObjectFrame");
michael@0 100 return sLog;
michael@0 101 }
michael@0 102 #endif /* PR_LOGGING */
michael@0 103
michael@0 104 #if defined(XP_MACOSX) && !defined(__LP64__)
michael@0 105
michael@0 106 // The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
michael@0 107 // and up (though the QuickDraw APIs defined in them are still present) -- so
michael@0 108 // we need to supply the relevant parts of their contents here. It's likely
michael@0 109 // that Apple will eventually remove the APIs themselves (probably in OS X
michael@0 110 // 10.8), so we need to make them weak imports, and test for their presence
michael@0 111 // before using them.
michael@0 112 extern "C" {
michael@0 113 #if !defined(__QUICKDRAWAPI__)
michael@0 114 extern void SetRect(
michael@0 115 Rect * r,
michael@0 116 short left,
michael@0 117 short top,
michael@0 118 short right,
michael@0 119 short bottom)
michael@0 120 __attribute__((weak_import));
michael@0 121 #endif /* __QUICKDRAWAPI__ */
michael@0 122
michael@0 123 #if !defined(__QDOFFSCREEN__)
michael@0 124 extern QDErr NewGWorldFromPtr(
michael@0 125 GWorldPtr * offscreenGWorld,
michael@0 126 UInt32 PixelFormat,
michael@0 127 const Rect * boundsRect,
michael@0 128 CTabHandle cTable, /* can be nullptr */
michael@0 129 GDHandle aGDevice, /* can be nullptr */
michael@0 130 GWorldFlags flags,
michael@0 131 Ptr newBuffer,
michael@0 132 SInt32 rowBytes)
michael@0 133 __attribute__((weak_import));
michael@0 134 extern void DisposeGWorld(GWorldPtr offscreenGWorld)
michael@0 135 __attribute__((weak_import));
michael@0 136 #endif /* __QDOFFSCREEN__ */
michael@0 137 }
michael@0 138
michael@0 139 #endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */
michael@0 140
michael@0 141 using namespace mozilla;
michael@0 142 using namespace mozilla::gfx;
michael@0 143 using namespace mozilla::layers;
michael@0 144
michael@0 145 class PluginBackgroundSink : public ReadbackSink {
michael@0 146 public:
michael@0 147 PluginBackgroundSink(nsObjectFrame* aFrame, uint64_t aStartSequenceNumber)
michael@0 148 : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
michael@0 149 ~PluginBackgroundSink()
michael@0 150 {
michael@0 151 if (mFrame) {
michael@0 152 mFrame->mBackgroundSink = nullptr;
michael@0 153 }
michael@0 154 }
michael@0 155
michael@0 156 virtual void SetUnknown(uint64_t aSequenceNumber)
michael@0 157 {
michael@0 158 if (!AcceptUpdate(aSequenceNumber))
michael@0 159 return;
michael@0 160 mFrame->mInstanceOwner->SetBackgroundUnknown();
michael@0 161 }
michael@0 162
michael@0 163 virtual already_AddRefed<gfxContext>
michael@0 164 BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber)
michael@0 165 {
michael@0 166 if (!AcceptUpdate(aSequenceNumber))
michael@0 167 return nullptr;
michael@0 168 return mFrame->mInstanceOwner->BeginUpdateBackground(aRect);
michael@0 169 }
michael@0 170
michael@0 171 virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect)
michael@0 172 {
michael@0 173 return mFrame->mInstanceOwner->EndUpdateBackground(aContext, aRect);
michael@0 174 }
michael@0 175
michael@0 176 void Destroy() { mFrame = nullptr; }
michael@0 177
michael@0 178 protected:
michael@0 179 bool AcceptUpdate(uint64_t aSequenceNumber) {
michael@0 180 if (aSequenceNumber > mLastSequenceNumber && mFrame &&
michael@0 181 mFrame->mInstanceOwner) {
michael@0 182 mLastSequenceNumber = aSequenceNumber;
michael@0 183 return true;
michael@0 184 }
michael@0 185 return false;
michael@0 186 }
michael@0 187
michael@0 188 uint64_t mLastSequenceNumber;
michael@0 189 nsObjectFrame* mFrame;
michael@0 190 };
michael@0 191
michael@0 192 nsObjectFrame::nsObjectFrame(nsStyleContext* aContext)
michael@0 193 : nsObjectFrameSuper(aContext)
michael@0 194 , mReflowCallbackPosted(false)
michael@0 195 {
michael@0 196 PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
michael@0 197 ("Created new nsObjectFrame %p\n", this));
michael@0 198 }
michael@0 199
michael@0 200 nsObjectFrame::~nsObjectFrame()
michael@0 201 {
michael@0 202 PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
michael@0 203 ("nsObjectFrame %p deleted\n", this));
michael@0 204 }
michael@0 205
michael@0 206 NS_QUERYFRAME_HEAD(nsObjectFrame)
michael@0 207 NS_QUERYFRAME_ENTRY(nsObjectFrame)
michael@0 208 NS_QUERYFRAME_ENTRY(nsIObjectFrame)
michael@0 209 NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper)
michael@0 210
michael@0 211 #ifdef ACCESSIBILITY
michael@0 212 a11y::AccType
michael@0 213 nsObjectFrame::AccessibleType()
michael@0 214 {
michael@0 215 return a11y::ePluginType;
michael@0 216 }
michael@0 217
michael@0 218 #ifdef XP_WIN
michael@0 219 NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
michael@0 220 {
michael@0 221 *aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
michael@0 222 return NS_OK;
michael@0 223 }
michael@0 224 #endif
michael@0 225 #endif
michael@0 226
michael@0 227 void
michael@0 228 nsObjectFrame::Init(nsIContent* aContent,
michael@0 229 nsIFrame* aParent,
michael@0 230 nsIFrame* aPrevInFlow)
michael@0 231 {
michael@0 232 PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG,
michael@0 233 ("Initializing nsObjectFrame %p for content %p\n", this, aContent));
michael@0 234
michael@0 235 nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
michael@0 236 }
michael@0 237
michael@0 238 void
michael@0 239 nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
michael@0 240 {
michael@0 241 if (mReflowCallbackPosted) {
michael@0 242 PresContext()->PresShell()->CancelReflowCallback(this);
michael@0 243 }
michael@0 244
michael@0 245 // Tell content owner of the instance to disconnect its frame.
michael@0 246 nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
michael@0 247 NS_ASSERTION(objContent, "Why not an object loading content?");
michael@0 248
michael@0 249 // The content might not have a reference to the instance owner any longer in
michael@0 250 // the case of re-entry during instantiation or teardown, so make sure we're
michael@0 251 // dissociated.
michael@0 252 if (mInstanceOwner) {
michael@0 253 mInstanceOwner->SetFrame(nullptr);
michael@0 254 }
michael@0 255 objContent->HasNewFrame(nullptr);
michael@0 256
michael@0 257 if (mBackgroundSink) {
michael@0 258 mBackgroundSink->Destroy();
michael@0 259 }
michael@0 260
michael@0 261 nsObjectFrameSuper::DestroyFrom(aDestructRoot);
michael@0 262 }
michael@0 263
michael@0 264 /* virtual */ void
michael@0 265 nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
michael@0 266 {
michael@0 267 if (HasView()) {
michael@0 268 nsView* view = GetView();
michael@0 269 nsViewManager* vm = view->GetViewManager();
michael@0 270 if (vm) {
michael@0 271 nsViewVisibility visibility =
michael@0 272 IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
michael@0 273 vm->SetViewVisibility(view, visibility);
michael@0 274 }
michael@0 275 }
michael@0 276
michael@0 277 nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext);
michael@0 278 }
michael@0 279
michael@0 280 nsIAtom*
michael@0 281 nsObjectFrame::GetType() const
michael@0 282 {
michael@0 283 return nsGkAtoms::objectFrame;
michael@0 284 }
michael@0 285
michael@0 286 #ifdef DEBUG_FRAME_DUMP
michael@0 287 nsresult
michael@0 288 nsObjectFrame::GetFrameName(nsAString& aResult) const
michael@0 289 {
michael@0 290 return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult);
michael@0 291 }
michael@0 292 #endif
michael@0 293
michael@0 294 nsresult
michael@0 295 nsObjectFrame::PrepForDrawing(nsIWidget *aWidget)
michael@0 296 {
michael@0 297 mWidget = aWidget;
michael@0 298
michael@0 299 nsView* view = GetView();
michael@0 300 NS_ASSERTION(view, "Object frames must have views");
michael@0 301 if (!view) {
michael@0 302 return NS_ERROR_FAILURE;
michael@0 303 }
michael@0 304
michael@0 305 nsViewManager* viewMan = view->GetViewManager();
michael@0 306 // mark the view as hidden since we don't know the (x,y) until Paint
michael@0 307 // XXX is the above comment correct?
michael@0 308 viewMan->SetViewVisibility(view, nsViewVisibility_kHide);
michael@0 309
michael@0 310 //this is ugly. it was ripped off from didreflow(). MMP
michael@0 311 // Position and size view relative to its parent, not relative to our
michael@0 312 // parent frame (our parent frame may not have a view).
michael@0 313
michael@0 314 nsView* parentWithView;
michael@0 315 nsPoint origin;
michael@0 316 nsRect r(0, 0, mRect.width, mRect.height);
michael@0 317
michael@0 318 GetOffsetFromView(origin, &parentWithView);
michael@0 319 viewMan->ResizeView(view, r);
michael@0 320 viewMan->MoveViewTo(view, origin.x, origin.y);
michael@0 321
michael@0 322 nsPresContext* presContext = PresContext();
michael@0 323 nsRootPresContext* rpc = presContext->GetRootPresContext();
michael@0 324 if (!rpc) {
michael@0 325 return NS_ERROR_FAILURE;
michael@0 326 }
michael@0 327
michael@0 328 if (mWidget) {
michael@0 329 // Disallow windowed plugins in popups
michael@0 330 nsIFrame* rootFrame = rpc->PresShell()->FrameManager()->GetRootFrame();
michael@0 331 nsIWidget* parentWidget = rootFrame->GetNearestWidget();
michael@0 332 if (!parentWidget || nsLayoutUtils::GetDisplayRootFrame(this) != rootFrame) {
michael@0 333 return NS_ERROR_FAILURE;
michael@0 334 }
michael@0 335
michael@0 336 mInnerView = viewMan->CreateView(GetContentRectRelativeToSelf(), view);
michael@0 337 if (!mInnerView) {
michael@0 338 NS_ERROR("Could not create inner view");
michael@0 339 return NS_ERROR_OUT_OF_MEMORY;
michael@0 340 }
michael@0 341 viewMan->InsertChild(view, mInnerView, nullptr, true);
michael@0 342
michael@0 343 mWidget->SetParent(parentWidget);
michael@0 344 mWidget->Show(true);
michael@0 345 mWidget->Enable(true);
michael@0 346
michael@0 347 // Set the plugin window to have an empty clip region until we know
michael@0 348 // what our true position, size and clip region are. These
michael@0 349 // will be reset when nsRootPresContext computes our true
michael@0 350 // geometry. The plugin window does need to have a good size here, so
michael@0 351 // set the size explicitly to a reasonable guess.
michael@0 352 nsAutoTArray<nsIWidget::Configuration,1> configurations;
michael@0 353 nsIWidget::Configuration* configuration = configurations.AppendElement();
michael@0 354 nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
michael@0 355 configuration->mChild = mWidget;
michael@0 356 configuration->mBounds.width = NSAppUnitsToIntPixels(mRect.width, appUnitsPerDevPixel);
michael@0 357 configuration->mBounds.height = NSAppUnitsToIntPixels(mRect.height, appUnitsPerDevPixel);
michael@0 358 parentWidget->ConfigureChildren(configurations);
michael@0 359
michael@0 360 nsRefPtr<nsDeviceContext> dx = viewMan->GetDeviceContext();
michael@0 361 mInnerView->AttachWidgetEventHandler(mWidget);
michael@0 362
michael@0 363 #ifdef XP_MACOSX
michael@0 364 // On Mac, we need to invalidate ourselves since even windowed
michael@0 365 // plugins are painted through Thebes and we need to ensure
michael@0 366 // the Thebes layer containing the plugin is updated.
michael@0 367 if (parentWidget == GetNearestWidget()) {
michael@0 368 InvalidateFrame();
michael@0 369 }
michael@0 370 #endif
michael@0 371
michael@0 372 RegisterPluginForGeometryUpdates();
michael@0 373
michael@0 374 // Here we set the background color for this widget because some plugins will use
michael@0 375 // the child window background color when painting. If it's not set, it may default to gray
michael@0 376 // Sometimes, a frame doesn't have a background color or is transparent. In this
michael@0 377 // case, walk up the frame tree until we do find a frame with a background color
michael@0 378 for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
michael@0 379 nscolor bgcolor =
michael@0 380 frame->GetVisitedDependentColor(eCSSProperty_background_color);
michael@0 381 if (NS_GET_A(bgcolor) > 0) { // make sure we got an actual color
michael@0 382 mWidget->SetBackgroundColor(bgcolor);
michael@0 383 break;
michael@0 384 }
michael@0 385 }
michael@0 386 } else {
michael@0 387 // Changing to windowless mode changes the NPWindow geometry.
michael@0 388 FixupWindow(GetContentRectRelativeToSelf().Size());
michael@0 389
michael@0 390 #ifndef XP_MACOSX
michael@0 391 RegisterPluginForGeometryUpdates();
michael@0 392 #endif
michael@0 393 }
michael@0 394
michael@0 395 if (!IsHidden()) {
michael@0 396 viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
michael@0 397 }
michael@0 398
michael@0 399 #ifdef ACCESSIBILITY
michael@0 400 nsAccessibilityService* accService = nsIPresShell::AccService();
michael@0 401 if (accService) {
michael@0 402 accService->RecreateAccessible(PresContext()->PresShell(), mContent);
michael@0 403 }
michael@0 404 #endif
michael@0 405
michael@0 406 return NS_OK;
michael@0 407 }
michael@0 408
michael@0 409 #define EMBED_DEF_WIDTH 240
michael@0 410 #define EMBED_DEF_HEIGHT 200
michael@0 411
michael@0 412 /* virtual */ nscoord
michael@0 413 nsObjectFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
michael@0 414 {
michael@0 415 nscoord result = 0;
michael@0 416
michael@0 417 if (!IsHidden(false)) {
michael@0 418 nsIAtom *atom = mContent->Tag();
michael@0 419 if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
michael@0 420 result = nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH);
michael@0 421 }
michael@0 422 }
michael@0 423
michael@0 424 DISPLAY_MIN_WIDTH(this, result);
michael@0 425 return result;
michael@0 426 }
michael@0 427
michael@0 428 /* virtual */ nscoord
michael@0 429 nsObjectFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
michael@0 430 {
michael@0 431 return nsObjectFrame::GetMinWidth(aRenderingContext);
michael@0 432 }
michael@0 433
michael@0 434 void
michael@0 435 nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
michael@0 436 const nsHTMLReflowState& aReflowState,
michael@0 437 nsHTMLReflowMetrics& aMetrics)
michael@0 438 {
michael@0 439 // By default, we have no area
michael@0 440 aMetrics.Width() = 0;
michael@0 441 aMetrics.Height() = 0;
michael@0 442
michael@0 443 if (IsHidden(false)) {
michael@0 444 return;
michael@0 445 }
michael@0 446
michael@0 447 aMetrics.Width() = aReflowState.ComputedWidth();
michael@0 448 aMetrics.Height() = aReflowState.ComputedHeight();
michael@0 449
michael@0 450 // for EMBED and APPLET, default to 240x200 for compatibility
michael@0 451 nsIAtom *atom = mContent->Tag();
michael@0 452 if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
michael@0 453 if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
michael@0 454 aMetrics.Width() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
michael@0 455 aReflowState.ComputedMinWidth(),
michael@0 456 aReflowState.ComputedMaxWidth());
michael@0 457 }
michael@0 458 if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
michael@0 459 aMetrics.Height() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
michael@0 460 aReflowState.ComputedMinHeight(),
michael@0 461 aReflowState.ComputedMaxHeight());
michael@0 462 }
michael@0 463
michael@0 464 #if defined(MOZ_WIDGET_GTK)
michael@0 465 // We need to make sure that the size of the object frame does not
michael@0 466 // exceed the maximum size of X coordinates. See bug #225357 for
michael@0 467 // more information. In theory Gtk2 can handle large coordinates,
michael@0 468 // but underlying plugins can't.
michael@0 469 aMetrics.Height() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Height());
michael@0 470 aMetrics.Width() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Width());
michael@0 471 #endif
michael@0 472 }
michael@0 473
michael@0 474 // At this point, the width has an unconstrained value only if we have
michael@0 475 // nothing to go on (no width set, no information from the plugin, nothing).
michael@0 476 // Make up a number.
michael@0 477 if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) {
michael@0 478 aMetrics.Width() =
michael@0 479 (aReflowState.ComputedMinWidth() != NS_UNCONSTRAINEDSIZE) ?
michael@0 480 aReflowState.ComputedMinWidth() : 0;
michael@0 481 }
michael@0 482
michael@0 483 // At this point, the height has an unconstrained value only in two cases:
michael@0 484 // a) We are in standards mode with percent heights and parent is auto-height
michael@0 485 // b) We have no height information at all.
michael@0 486 // In either case, we have to make up a number.
michael@0 487 if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) {
michael@0 488 aMetrics.Height() =
michael@0 489 (aReflowState.ComputedMinHeight() != NS_UNCONSTRAINEDSIZE) ?
michael@0 490 aReflowState.ComputedMinHeight() : 0;
michael@0 491 }
michael@0 492
michael@0 493 // XXXbz don't add in the border and padding, because we screw up our
michael@0 494 // plugin's size and positioning if we do... Eventually we _do_ want to
michael@0 495 // paint borders, though! At that point, we will need to adjust the desired
michael@0 496 // size either here or in Reflow.... Further, we will need to fix Paint() to
michael@0 497 // call the superclass in all cases.
michael@0 498 }
michael@0 499
michael@0 500 nsresult
michael@0 501 nsObjectFrame::Reflow(nsPresContext* aPresContext,
michael@0 502 nsHTMLReflowMetrics& aMetrics,
michael@0 503 const nsHTMLReflowState& aReflowState,
michael@0 504 nsReflowStatus& aStatus)
michael@0 505 {
michael@0 506 DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
michael@0 507 DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
michael@0 508
michael@0 509 // Get our desired size
michael@0 510 GetDesiredSize(aPresContext, aReflowState, aMetrics);
michael@0 511 aMetrics.SetOverflowAreasToDesiredBounds();
michael@0 512 FinishAndStoreOverflow(&aMetrics);
michael@0 513
michael@0 514 // delay plugin instantiation until all children have
michael@0 515 // arrived. Otherwise there may be PARAMs or other stuff that the
michael@0 516 // plugin needs to see that haven't arrived yet.
michael@0 517 if (!GetContent()->IsDoneAddingChildren()) {
michael@0 518 aStatus = NS_FRAME_COMPLETE;
michael@0 519 return NS_OK;
michael@0 520 }
michael@0 521
michael@0 522 // if we are printing or print previewing, bail for now
michael@0 523 if (aPresContext->Medium() == nsGkAtoms::print) {
michael@0 524 aStatus = NS_FRAME_COMPLETE;
michael@0 525 return NS_OK;
michael@0 526 }
michael@0 527
michael@0 528 nsRect r(0, 0, aMetrics.Width(), aMetrics.Height());
michael@0 529 r.Deflate(aReflowState.ComputedPhysicalBorderPadding());
michael@0 530
michael@0 531 if (mInnerView) {
michael@0 532 nsViewManager* vm = mInnerView->GetViewManager();
michael@0 533 vm->MoveViewTo(mInnerView, r.x, r.y);
michael@0 534 vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), r.Size()), true);
michael@0 535 }
michael@0 536
michael@0 537 FixupWindow(r.Size());
michael@0 538 if (!mReflowCallbackPosted) {
michael@0 539 mReflowCallbackPosted = true;
michael@0 540 aPresContext->PresShell()->PostReflowCallback(this);
michael@0 541 }
michael@0 542
michael@0 543 aStatus = NS_FRAME_COMPLETE;
michael@0 544
michael@0 545 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
michael@0 546 return NS_OK;
michael@0 547 }
michael@0 548
michael@0 549 ///////////// nsIReflowCallback ///////////////
michael@0 550
michael@0 551 bool
michael@0 552 nsObjectFrame::ReflowFinished()
michael@0 553 {
michael@0 554 mReflowCallbackPosted = false;
michael@0 555 CallSetWindow();
michael@0 556 return true;
michael@0 557 }
michael@0 558
michael@0 559 void
michael@0 560 nsObjectFrame::ReflowCallbackCanceled()
michael@0 561 {
michael@0 562 mReflowCallbackPosted = false;
michael@0 563 }
michael@0 564
michael@0 565 void
michael@0 566 nsObjectFrame::FixupWindow(const nsSize& aSize)
michael@0 567 {
michael@0 568 nsPresContext* presContext = PresContext();
michael@0 569
michael@0 570 if (!mInstanceOwner)
michael@0 571 return;
michael@0 572
michael@0 573 NPWindow *window;
michael@0 574 mInstanceOwner->GetWindow(window);
michael@0 575
michael@0 576 NS_ENSURE_TRUE_VOID(window);
michael@0 577
michael@0 578 #ifdef XP_MACOSX
michael@0 579 nsWeakFrame weakFrame(this);
michael@0 580 mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
michael@0 581 if (!weakFrame.IsAlive()) {
michael@0 582 return;
michael@0 583 }
michael@0 584 #endif
michael@0 585
michael@0 586 bool windowless = (window->type == NPWindowTypeDrawable);
michael@0 587
michael@0 588 nsIntPoint origin = GetWindowOriginInPixels(windowless);
michael@0 589
michael@0 590 // window must be in "display pixels"
michael@0 591 double scaleFactor = 1.0;
michael@0 592 if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
michael@0 593 scaleFactor = 1.0;
michael@0 594 }
michael@0 595 int intScaleFactor = ceil(scaleFactor);
michael@0 596 window->x = origin.x / intScaleFactor;
michael@0 597 window->y = origin.y / intScaleFactor;
michael@0 598 window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
michael@0 599 window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
michael@0 600
michael@0 601 // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
michael@0 602 // us from drawing on screen until the widget is properly positioned, which will not
michael@0 603 // happen until we have finished the reflow process.
michael@0 604 #ifdef XP_MACOSX
michael@0 605 window->clipRect.top = 0;
michael@0 606 window->clipRect.left = 0;
michael@0 607 window->clipRect.bottom = 0;
michael@0 608 window->clipRect.right = 0;
michael@0 609 #else
michael@0 610 mInstanceOwner->UpdateWindowPositionAndClipRect(false);
michael@0 611 #endif
michael@0 612
michael@0 613 NotifyPluginReflowObservers();
michael@0 614 }
michael@0 615
michael@0 616 nsresult
michael@0 617 nsObjectFrame::CallSetWindow(bool aCheckIsHidden)
michael@0 618 {
michael@0 619 NPWindow *win = nullptr;
michael@0 620
michael@0 621 nsresult rv = NS_ERROR_FAILURE;
michael@0 622 nsRefPtr<nsNPAPIPluginInstance> pi;
michael@0 623 if (!mInstanceOwner ||
michael@0 624 NS_FAILED(rv = mInstanceOwner->GetInstance(getter_AddRefs(pi))) ||
michael@0 625 !pi ||
michael@0 626 NS_FAILED(rv = mInstanceOwner->GetWindow(win)) ||
michael@0 627 !win)
michael@0 628 return rv;
michael@0 629
michael@0 630 nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
michael@0 631 #ifdef XP_MACOSX
michael@0 632 nsWeakFrame weakFrame(this);
michael@0 633 mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
michael@0 634 if (!weakFrame.IsAlive()) {
michael@0 635 return NS_ERROR_NOT_AVAILABLE;
michael@0 636 }
michael@0 637 #endif
michael@0 638
michael@0 639 if (aCheckIsHidden && IsHidden())
michael@0 640 return NS_ERROR_FAILURE;
michael@0 641
michael@0 642 // refresh the plugin port as well
michael@0 643 window->window = mInstanceOwner->GetPluginPortFromWidget();
michael@0 644
michael@0 645 // Adjust plugin dimensions according to pixel snap results
michael@0 646 // and reduce amount of SetWindow calls
michael@0 647 nsPresContext* presContext = PresContext();
michael@0 648 nsRootPresContext* rootPC = presContext->GetRootPresContext();
michael@0 649 if (!rootPC)
michael@0 650 return NS_ERROR_FAILURE;
michael@0 651 int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
michael@0 652 nsIFrame* rootFrame = rootPC->PresShell()->FrameManager()->GetRootFrame();
michael@0 653 nsRect bounds = GetContentRectRelativeToSelf() + GetOffsetToCrossDoc(rootFrame);
michael@0 654 nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
michael@0 655
michael@0 656 // window must be in "display pixels"
michael@0 657 double scaleFactor = 1.0;
michael@0 658 if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
michael@0 659 scaleFactor = 1.0;
michael@0 660 }
michael@0 661 size_t intScaleFactor = ceil(scaleFactor);
michael@0 662 window->x = intBounds.x / intScaleFactor;
michael@0 663 window->y = intBounds.y / intScaleFactor;
michael@0 664 window->width = intBounds.width / intScaleFactor;
michael@0 665 window->height = intBounds.height / intScaleFactor;
michael@0 666
michael@0 667 // Calling SetWindow might destroy this frame. We need to use the instance
michael@0 668 // owner to clean up so hold a ref.
michael@0 669 nsRefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner);
michael@0 670
michael@0 671 // This will call pi->SetWindow and take care of window subclassing
michael@0 672 // if needed, see bug 132759. Calling SetWindow can destroy this frame
michael@0 673 // so check for that before doing anything else with this frame's memory.
michael@0 674 if (mInstanceOwner->UseAsyncRendering()) {
michael@0 675 rv = pi->AsyncSetWindow(window);
michael@0 676 }
michael@0 677 else {
michael@0 678 rv = window->CallSetWindow(pi);
michael@0 679 }
michael@0 680
michael@0 681 instanceOwnerRef->ReleasePluginPort(window->window);
michael@0 682
michael@0 683 return rv;
michael@0 684 }
michael@0 685
michael@0 686 void
michael@0 687 nsObjectFrame::RegisterPluginForGeometryUpdates()
michael@0 688 {
michael@0 689 nsRootPresContext* rpc = PresContext()->GetRootPresContext();
michael@0 690 NS_ASSERTION(rpc, "We should have a root pres context!");
michael@0 691 if (mRootPresContextRegisteredWith == rpc || !rpc) {
michael@0 692 // Already registered with current root pres context,
michael@0 693 // or null root pres context...
michael@0 694 return;
michael@0 695 }
michael@0 696 if (mRootPresContextRegisteredWith && mRootPresContextRegisteredWith != rpc) {
michael@0 697 // Registered to some other root pres context. Unregister, and
michael@0 698 // re-register with our current one...
michael@0 699 UnregisterPluginForGeometryUpdates();
michael@0 700 }
michael@0 701 mRootPresContextRegisteredWith = rpc;
michael@0 702 mRootPresContextRegisteredWith->RegisterPluginForGeometryUpdates(mContent);
michael@0 703 }
michael@0 704
michael@0 705 void
michael@0 706 nsObjectFrame::UnregisterPluginForGeometryUpdates()
michael@0 707 {
michael@0 708 if (!mRootPresContextRegisteredWith) {
michael@0 709 // Not registered...
michael@0 710 return;
michael@0 711 }
michael@0 712 mRootPresContextRegisteredWith->UnregisterPluginForGeometryUpdates(mContent);
michael@0 713 mRootPresContextRegisteredWith = nullptr;
michael@0 714 }
michael@0 715
michael@0 716 void
michael@0 717 nsObjectFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner)
michael@0 718 {
michael@0 719 // The ownership model here is historically fuzzy. This should only be called
michael@0 720 // by nsPluginInstanceOwner when it is given a new frame, and
michael@0 721 // nsObjectLoadingContent should be arbitrating frame-ownership via its
michael@0 722 // HasNewFrame callback.
michael@0 723 mInstanceOwner = aOwner;
michael@0 724 if (mInstanceOwner) {
michael@0 725 return;
michael@0 726 }
michael@0 727 UnregisterPluginForGeometryUpdates();
michael@0 728 if (mWidget && mInnerView) {
michael@0 729 mInnerView->DetachWidgetEventHandler(mWidget);
michael@0 730 // Make sure the plugin is hidden in case an update of plugin geometry
michael@0 731 // hasn't happened since this plugin became hidden.
michael@0 732 nsIWidget* parent = mWidget->GetParent();
michael@0 733 if (parent) {
michael@0 734 nsTArray<nsIWidget::Configuration> configurations;
michael@0 735 nsIWidget::Configuration* configuration = configurations.AppendElement();
michael@0 736 configuration->mChild = mWidget;
michael@0 737 parent->ConfigureChildren(configurations);
michael@0 738
michael@0 739 mWidget->Show(false);
michael@0 740 mWidget->Enable(false);
michael@0 741 mWidget->SetParent(nullptr);
michael@0 742 }
michael@0 743 }
michael@0 744 }
michael@0 745
michael@0 746 bool
michael@0 747 nsObjectFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse)
michael@0 748 {
michael@0 749 if (aTabIndex)
michael@0 750 *aTabIndex = -1;
michael@0 751 return nsObjectFrameSuper::IsFocusable(aTabIndex, aWithMouse);
michael@0 752 }
michael@0 753
michael@0 754 bool
michael@0 755 nsObjectFrame::IsHidden(bool aCheckVisibilityStyle) const
michael@0 756 {
michael@0 757 if (aCheckVisibilityStyle) {
michael@0 758 if (!StyleVisibility()->IsVisibleOrCollapsed())
michael@0 759 return true;
michael@0 760 }
michael@0 761
michael@0 762 // only <embed> tags support the HIDDEN attribute
michael@0 763 if (mContent->Tag() == nsGkAtoms::embed) {
michael@0 764 // Yes, these are really the kooky ways that you could tell 4.x
michael@0 765 // not to hide the <embed> once you'd put the 'hidden' attribute
michael@0 766 // on the tag...
michael@0 767
michael@0 768 // HIDDEN w/ no attributes gets translated as we are hidden for
michael@0 769 // compatibility w/ 4.x and IE so we don't create a non-painting
michael@0 770 // widget in layout. See bug 188959.
michael@0 771 nsAutoString hidden;
michael@0 772 if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::hidden, hidden) &&
michael@0 773 (hidden.IsEmpty() ||
michael@0 774 (!hidden.LowerCaseEqualsLiteral("false") &&
michael@0 775 !hidden.LowerCaseEqualsLiteral("no") &&
michael@0 776 !hidden.LowerCaseEqualsLiteral("off")))) {
michael@0 777 return true;
michael@0 778 }
michael@0 779 }
michael@0 780
michael@0 781 return false;
michael@0 782 }
michael@0 783
michael@0 784 nsIntPoint nsObjectFrame::GetWindowOriginInPixels(bool aWindowless)
michael@0 785 {
michael@0 786 nsView * parentWithView;
michael@0 787 nsPoint origin(0,0);
michael@0 788
michael@0 789 GetOffsetFromView(origin, &parentWithView);
michael@0 790
michael@0 791 // if it's windowless, let's make sure we have our origin set right
michael@0 792 // it may need to be corrected, like after scrolling
michael@0 793 if (aWindowless && parentWithView) {
michael@0 794 nsPoint offsetToWidget;
michael@0 795 parentWithView->GetNearestWidget(&offsetToWidget);
michael@0 796 origin += offsetToWidget;
michael@0 797 }
michael@0 798 origin += GetContentRectRelativeToSelf().TopLeft();
michael@0 799
michael@0 800 return nsIntPoint(PresContext()->AppUnitsToDevPixels(origin.x),
michael@0 801 PresContext()->AppUnitsToDevPixels(origin.y));
michael@0 802 }
michael@0 803
michael@0 804 nsresult
michael@0 805 nsObjectFrame::DidReflow(nsPresContext* aPresContext,
michael@0 806 const nsHTMLReflowState* aReflowState,
michael@0 807 nsDidReflowStatus aStatus)
michael@0 808 {
michael@0 809 // Do this check before calling the superclass, as that clears
michael@0 810 // NS_FRAME_FIRST_REFLOW
michael@0 811 if (aStatus == nsDidReflowStatus::FINISHED &&
michael@0 812 (GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
michael@0 813 nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
michael@0 814 NS_ASSERTION(objContent, "Why not an object loading content?");
michael@0 815 objContent->HasNewFrame(this);
michael@0 816 }
michael@0 817
michael@0 818 nsresult rv = nsObjectFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
michael@0 819
michael@0 820 // The view is created hidden; once we have reflowed it and it has been
michael@0 821 // positioned then we show it.
michael@0 822 if (aStatus != nsDidReflowStatus::FINISHED)
michael@0 823 return rv;
michael@0 824
michael@0 825 if (HasView()) {
michael@0 826 nsView* view = GetView();
michael@0 827 nsViewManager* vm = view->GetViewManager();
michael@0 828 if (vm)
michael@0 829 vm->SetViewVisibility(view, IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow);
michael@0 830 }
michael@0 831
michael@0 832 return rv;
michael@0 833 }
michael@0 834
michael@0 835 /* static */ void
michael@0 836 nsObjectFrame::PaintPrintPlugin(nsIFrame* aFrame, nsRenderingContext* aCtx,
michael@0 837 const nsRect& aDirtyRect, nsPoint aPt)
michael@0 838 {
michael@0 839 nsPoint pt = aPt + aFrame->GetContentRectRelativeToSelf().TopLeft();
michael@0 840 nsRenderingContext::AutoPushTranslation translate(aCtx, pt);
michael@0 841 // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
michael@0 842 static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
michael@0 843 }
michael@0 844
michael@0 845 class nsDisplayPluginReadback : public nsDisplayItem {
michael@0 846 public:
michael@0 847 nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
michael@0 848 : nsDisplayItem(aBuilder, aFrame)
michael@0 849 {
michael@0 850 MOZ_COUNT_CTOR(nsDisplayPluginReadback);
michael@0 851 }
michael@0 852 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 853 virtual ~nsDisplayPluginReadback() {
michael@0 854 MOZ_COUNT_DTOR(nsDisplayPluginReadback);
michael@0 855 }
michael@0 856 #endif
michael@0 857
michael@0 858 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
michael@0 859 bool* aSnap) MOZ_OVERRIDE;
michael@0 860 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 861 nsRegion* aVisibleRegion,
michael@0 862 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 863
michael@0 864 NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK)
michael@0 865
michael@0 866 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 867 LayerManager* aManager,
michael@0 868 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
michael@0 869 {
michael@0 870 return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
michael@0 871 }
michael@0 872
michael@0 873 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 874 LayerManager* aManager,
michael@0 875 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
michael@0 876 {
michael@0 877 return LAYER_ACTIVE;
michael@0 878 }
michael@0 879 };
michael@0 880
michael@0 881 static nsRect
michael@0 882 GetDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
michael@0 883 {
michael@0 884 // XXX For slightly more accurate region computations we should pixel-snap this
michael@0 885 return aFrame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
michael@0 886 }
michael@0 887
michael@0 888 nsRect
michael@0 889 nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
michael@0 890 {
michael@0 891 *aSnap = false;
michael@0 892 return GetDisplayItemBounds(aBuilder, this, mFrame);
michael@0 893 }
michael@0 894
michael@0 895 bool
michael@0 896 nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 897 nsRegion* aVisibleRegion,
michael@0 898 const nsRect& aAllowVisibleRegionExpansion)
michael@0 899 {
michael@0 900 if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
michael@0 901 aAllowVisibleRegionExpansion))
michael@0 902 return false;
michael@0 903
michael@0 904 nsRect expand;
michael@0 905 bool snap;
michael@0 906 expand.IntersectRect(aAllowVisibleRegionExpansion, GetBounds(aBuilder, &snap));
michael@0 907 // *Add* our bounds to the visible region so that stuff underneath us is
michael@0 908 // likely to be made visible, so we can use it for a background! This is
michael@0 909 // a bit crazy since we normally only subtract from the visible region.
michael@0 910 aVisibleRegion->Or(*aVisibleRegion, expand);
michael@0 911 return true;
michael@0 912 }
michael@0 913
michael@0 914 #ifdef MOZ_WIDGET_ANDROID
michael@0 915
michael@0 916 class nsDisplayPluginVideo : public nsDisplayItem {
michael@0 917 public:
michael@0 918 nsDisplayPluginVideo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
michael@0 919 : nsDisplayItem(aBuilder, aFrame), mVideoInfo(aVideoInfo)
michael@0 920 {
michael@0 921 MOZ_COUNT_CTOR(nsDisplayPluginVideo);
michael@0 922 }
michael@0 923 #ifdef NS_BUILD_REFCNT_LOGGING
michael@0 924 virtual ~nsDisplayPluginVideo() {
michael@0 925 MOZ_COUNT_DTOR(nsDisplayPluginVideo);
michael@0 926 }
michael@0 927 #endif
michael@0 928
michael@0 929 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
michael@0 930 bool* aSnap) MOZ_OVERRIDE;
michael@0 931 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 932 nsRegion* aVisibleRegion,
michael@0 933 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
michael@0 934
michael@0 935 NS_DISPLAY_DECL_NAME("PluginVideo", TYPE_PLUGIN_VIDEO)
michael@0 936
michael@0 937 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 938 LayerManager* aManager,
michael@0 939 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
michael@0 940 {
michael@0 941 return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
michael@0 942 }
michael@0 943
michael@0 944 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 945 LayerManager* aManager,
michael@0 946 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
michael@0 947 {
michael@0 948 return LAYER_ACTIVE;
michael@0 949 }
michael@0 950
michael@0 951 nsNPAPIPluginInstance::VideoInfo* VideoInfo() { return mVideoInfo; }
michael@0 952
michael@0 953 private:
michael@0 954 nsNPAPIPluginInstance::VideoInfo* mVideoInfo;
michael@0 955 };
michael@0 956
michael@0 957 nsRect
michael@0 958 nsDisplayPluginVideo::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
michael@0 959 {
michael@0 960 *aSnap = false;
michael@0 961 return GetDisplayItemBounds(aBuilder, this, mFrame);
michael@0 962 }
michael@0 963
michael@0 964 bool
michael@0 965 nsDisplayPluginVideo::ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 966 nsRegion* aVisibleRegion,
michael@0 967 const nsRect& aAllowVisibleRegionExpansion)
michael@0 968 {
michael@0 969 return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
michael@0 970 aAllowVisibleRegionExpansion);
michael@0 971 }
michael@0 972
michael@0 973 #endif
michael@0 974
michael@0 975 nsRect
michael@0 976 nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
michael@0 977 {
michael@0 978 *aSnap = true;
michael@0 979 return GetDisplayItemBounds(aBuilder, this, mFrame);
michael@0 980 }
michael@0 981
michael@0 982 void
michael@0 983 nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
michael@0 984 nsRenderingContext* aCtx)
michael@0 985 {
michael@0 986 nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
michael@0 987 bool snap;
michael@0 988 f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder, &snap));
michael@0 989 }
michael@0 990
michael@0 991 bool
michael@0 992 nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
michael@0 993 nsRegion* aVisibleRegion,
michael@0 994 const nsRect& aAllowVisibleRegionExpansion)
michael@0 995 {
michael@0 996 if (aBuilder->IsForPluginGeometry()) {
michael@0 997 nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
michael@0 998 if (!aBuilder->IsInTransform() || f->IsPaintedByGecko()) {
michael@0 999 // Since transforms induce reference frames, we don't need to worry
michael@0 1000 // about this method fluffing out due to non-rectilinear transforms.
michael@0 1001 nsRect rAncestor = nsLayoutUtils::TransformFrameRectToAncestor(f,
michael@0 1002 f->GetContentRectRelativeToSelf(), ReferenceFrame());
michael@0 1003 nscoord appUnitsPerDevPixel =
michael@0 1004 ReferenceFrame()->PresContext()->AppUnitsPerDevPixel();
michael@0 1005 f->mNextConfigurationBounds = rAncestor.ToNearestPixels(appUnitsPerDevPixel);
michael@0 1006
michael@0 1007 nsRegion visibleRegion;
michael@0 1008 visibleRegion.And(*aVisibleRegion, GetClippedBounds(aBuilder));
michael@0 1009 // Make visibleRegion relative to f
michael@0 1010 visibleRegion.MoveBy(-ToReferenceFrame());
michael@0 1011
michael@0 1012 f->mNextConfigurationClipRegion.Clear();
michael@0 1013 nsRegionRectIterator iter(visibleRegion);
michael@0 1014 for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
michael@0 1015 nsRect rAncestor =
michael@0 1016 nsLayoutUtils::TransformFrameRectToAncestor(f, *r, ReferenceFrame());
michael@0 1017 nsIntRect rPixels = rAncestor.ToNearestPixels(appUnitsPerDevPixel)
michael@0 1018 - f->mNextConfigurationBounds.TopLeft();
michael@0 1019 if (!rPixels.IsEmpty()) {
michael@0 1020 f->mNextConfigurationClipRegion.AppendElement(rPixels);
michael@0 1021 }
michael@0 1022 }
michael@0 1023 }
michael@0 1024
michael@0 1025 if (f->mInnerView) {
michael@0 1026 // This should produce basically the same rectangle (but not relative
michael@0 1027 // to the root frame). We only call this here for the side-effect of
michael@0 1028 // setting mViewToWidgetOffset on the view.
michael@0 1029 f->mInnerView->CalcWidgetBounds(eWindowType_plugin);
michael@0 1030 }
michael@0 1031 }
michael@0 1032
michael@0 1033 return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
michael@0 1034 aAllowVisibleRegionExpansion);
michael@0 1035 }
michael@0 1036
michael@0 1037 nsRegion
michael@0 1038 nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
michael@0 1039 bool* aSnap)
michael@0 1040 {
michael@0 1041 *aSnap = false;
michael@0 1042 nsRegion result;
michael@0 1043 nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
michael@0 1044 if (!aBuilder->IsForPluginGeometry()) {
michael@0 1045 nsIWidget* widget = f->GetWidget();
michael@0 1046 if (widget) {
michael@0 1047 // Be conservative and treat plugins with widgets as not opaque,
michael@0 1048 // because that's simple and we might need the content under the widget
michael@0 1049 // if the widget is unexpectedly clipped away. (As can happen when
michael@0 1050 // chrome content over a plugin forces us to clip out the plugin for
michael@0 1051 // security reasons.)
michael@0 1052 // We shouldn't be repainting the content under plugins much anyway
michael@0 1053 // since there generally shouldn't be anything to invalidate or paint
michael@0 1054 // in ThebesLayers there.
michael@0 1055 return result;
michael@0 1056 }
michael@0 1057 }
michael@0 1058
michael@0 1059 if (f->IsOpaque()) {
michael@0 1060 nsRect bounds = GetBounds(aBuilder, aSnap);
michael@0 1061 if (aBuilder->IsForPluginGeometry() ||
michael@0 1062 (f->GetPaintedRect(this) + ToReferenceFrame()).Contains(bounds)) {
michael@0 1063 // We can treat this as opaque
michael@0 1064 result = bounds;
michael@0 1065 }
michael@0 1066 }
michael@0 1067
michael@0 1068 return result;
michael@0 1069 }
michael@0 1070
michael@0 1071 nsresult
michael@0 1072 nsObjectFrame::PluginEventNotifier::Run() {
michael@0 1073 nsCOMPtr<nsIObserverService> obsSvc =
michael@0 1074 mozilla::services::GetObserverService();
michael@0 1075 obsSvc->NotifyObservers(nullptr, "plugin-changed-event", mEventType.get());
michael@0 1076 return NS_OK;
michael@0 1077 }
michael@0 1078
michael@0 1079 void
michael@0 1080 nsObjectFrame::NotifyPluginReflowObservers()
michael@0 1081 {
michael@0 1082 nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
michael@0 1083 }
michael@0 1084
michael@0 1085 void
michael@0 1086 nsObjectFrame::DidSetWidgetGeometry()
michael@0 1087 {
michael@0 1088 #if defined(XP_MACOSX)
michael@0 1089 if (mInstanceOwner) {
michael@0 1090 mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
michael@0 1091 }
michael@0 1092 #else
michael@0 1093 if (!mWidget && mInstanceOwner) {
michael@0 1094 // UpdateWindowVisibility will notify the plugin of position changes
michael@0 1095 // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
michael@0 1096 // We treat windowless plugins inside popups as always visible, since
michael@0 1097 // plugins inside popups don't get valid mNextConfigurationBounds
michael@0 1098 // set up.
michael@0 1099 mInstanceOwner->UpdateWindowVisibility(
michael@0 1100 nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
michael@0 1101 !mNextConfigurationBounds.IsEmpty());
michael@0 1102 }
michael@0 1103 #endif
michael@0 1104 }
michael@0 1105
michael@0 1106 bool
michael@0 1107 nsObjectFrame::IsOpaque() const
michael@0 1108 {
michael@0 1109 #if defined(XP_MACOSX)
michael@0 1110 // ???
michael@0 1111 return false;
michael@0 1112 #elif defined(MOZ_WIDGET_ANDROID)
michael@0 1113 // We don't know, so just assume transparent
michael@0 1114 return false;
michael@0 1115 #else
michael@0 1116 return !IsTransparentMode();
michael@0 1117 #endif
michael@0 1118 }
michael@0 1119
michael@0 1120 bool
michael@0 1121 nsObjectFrame::IsTransparentMode() const
michael@0 1122 {
michael@0 1123 #if defined(XP_MACOSX)
michael@0 1124 // ???
michael@0 1125 return false;
michael@0 1126 #else
michael@0 1127 if (!mInstanceOwner)
michael@0 1128 return false;
michael@0 1129
michael@0 1130 NPWindow *window = nullptr;
michael@0 1131 mInstanceOwner->GetWindow(window);
michael@0 1132 if (!window) {
michael@0 1133 return false;
michael@0 1134 }
michael@0 1135
michael@0 1136 if (window->type != NPWindowTypeDrawable)
michael@0 1137 return false;
michael@0 1138
michael@0 1139 nsresult rv;
michael@0 1140 nsRefPtr<nsNPAPIPluginInstance> pi;
michael@0 1141 rv = mInstanceOwner->GetInstance(getter_AddRefs(pi));
michael@0 1142 if (NS_FAILED(rv) || !pi)
michael@0 1143 return false;
michael@0 1144
michael@0 1145 bool transparent = false;
michael@0 1146 pi->IsTransparent(&transparent);
michael@0 1147 return transparent;
michael@0 1148 #endif
michael@0 1149 }
michael@0 1150
michael@0 1151 void
michael@0 1152 nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
michael@0 1153 const nsRect& aDirtyRect,
michael@0 1154 const nsDisplayListSet& aLists)
michael@0 1155 {
michael@0 1156 // XXX why are we painting collapsed object frames?
michael@0 1157 if (!IsVisibleOrCollapsedForPainting(aBuilder))
michael@0 1158 return;
michael@0 1159
michael@0 1160 DisplayBorderBackgroundOutline(aBuilder, aLists);
michael@0 1161
michael@0 1162 nsPresContext::nsPresContextType type = PresContext()->Type();
michael@0 1163
michael@0 1164 // If we are painting in Print Preview do nothing....
michael@0 1165 if (type == nsPresContext::eContext_PrintPreview)
michael@0 1166 return;
michael@0 1167
michael@0 1168 DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame");
michael@0 1169
michael@0 1170 #ifndef XP_MACOSX
michael@0 1171 if (mWidget && aBuilder->IsInTransform()) {
michael@0 1172 // Windowed plugins should not be rendered inside a transform.
michael@0 1173 return;
michael@0 1174 }
michael@0 1175 #endif
michael@0 1176
michael@0 1177 if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
michael@0 1178 NPWindow* window = nullptr;
michael@0 1179 mInstanceOwner->GetWindow(window);
michael@0 1180 bool isVisible = window && window->width > 0 && window->height > 0;
michael@0 1181 if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
michael@0 1182 #ifndef XP_MACOSX
michael@0 1183 mInstanceOwner->UpdateWindowVisibility(true);
michael@0 1184 #endif
michael@0 1185 }
michael@0 1186
michael@0 1187 mInstanceOwner->NotifyPaintWaiter(aBuilder);
michael@0 1188 }
michael@0 1189
michael@0 1190 DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
michael@0 1191 clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT);
michael@0 1192
michael@0 1193 // determine if we are printing
michael@0 1194 if (type == nsPresContext::eContext_Print) {
michael@0 1195 aLists.Content()->AppendNewToTop(new (aBuilder)
michael@0 1196 nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
michael@0 1197 nsDisplayItem::TYPE_PRINT_PLUGIN));
michael@0 1198 } else {
michael@0 1199 LayerState state = GetLayerState(aBuilder, nullptr);
michael@0 1200 if (state == LAYER_INACTIVE &&
michael@0 1201 nsDisplayItem::ForceActiveLayers()) {
michael@0 1202 state = LAYER_ACTIVE;
michael@0 1203 }
michael@0 1204 // We don't need this on Android, and it just confuses things
michael@0 1205 #if !MOZ_WIDGET_ANDROID
michael@0 1206 if (aBuilder->IsPaintingToWindow() &&
michael@0 1207 state == LAYER_ACTIVE &&
michael@0 1208 IsTransparentMode()) {
michael@0 1209 aLists.Content()->AppendNewToTop(new (aBuilder)
michael@0 1210 nsDisplayPluginReadback(aBuilder, this));
michael@0 1211 }
michael@0 1212 #endif
michael@0 1213
michael@0 1214 #if MOZ_WIDGET_ANDROID
michael@0 1215 if (aBuilder->IsPaintingToWindow() &&
michael@0 1216 state == LAYER_ACTIVE) {
michael@0 1217
michael@0 1218 nsTArray<nsNPAPIPluginInstance::VideoInfo*> videos;
michael@0 1219 mInstanceOwner->GetVideos(videos);
michael@0 1220
michael@0 1221 for (uint32_t i = 0; i < videos.Length(); i++) {
michael@0 1222 aLists.Content()->AppendNewToTop(new (aBuilder)
michael@0 1223 nsDisplayPluginVideo(aBuilder, this, videos[i]));
michael@0 1224 }
michael@0 1225 }
michael@0 1226 #endif
michael@0 1227
michael@0 1228 aLists.Content()->AppendNewToTop(new (aBuilder)
michael@0 1229 nsDisplayPlugin(aBuilder, this));
michael@0 1230 }
michael@0 1231 }
michael@0 1232
michael@0 1233 void
michael@0 1234 nsObjectFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
michael@0 1235 const nsRect& aDirtyRect)
michael@0 1236 {
michael@0 1237 nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent));
michael@0 1238 if (!obj)
michael@0 1239 return;
michael@0 1240
michael@0 1241 nsIFrame* frame = nullptr;
michael@0 1242 obj->GetPrintFrame(&frame);
michael@0 1243 if (!frame)
michael@0 1244 return;
michael@0 1245
michael@0 1246 nsPresContext* presContext = PresContext();
michael@0 1247 // make sure this is REALLY an nsIObjectFrame
michael@0 1248 // we may need to go through the children to get it
michael@0 1249 nsIObjectFrame* objectFrame = do_QueryFrame(frame);
michael@0 1250 if (!objectFrame)
michael@0 1251 objectFrame = GetNextObjectFrame(presContext,frame);
michael@0 1252 if (!objectFrame)
michael@0 1253 return;
michael@0 1254
michael@0 1255 // finally we can get our plugin instance
michael@0 1256 nsRefPtr<nsNPAPIPluginInstance> pi;
michael@0 1257 if (NS_FAILED(objectFrame->GetPluginInstance(getter_AddRefs(pi))) || !pi)
michael@0 1258 return;
michael@0 1259
michael@0 1260 // now we need to setup the correct location for printing
michael@0 1261 NPWindow window;
michael@0 1262 window.window = nullptr;
michael@0 1263
michael@0 1264 // prepare embedded mode printing struct
michael@0 1265 NPPrint npprint;
michael@0 1266 npprint.mode = NP_EMBED;
michael@0 1267
michael@0 1268 // we need to find out if we are windowless or not
michael@0 1269 bool windowless = false;
michael@0 1270 pi->IsWindowless(&windowless);
michael@0 1271 window.type = windowless ? NPWindowTypeDrawable : NPWindowTypeWindow;
michael@0 1272
michael@0 1273 window.clipRect.bottom = 0; window.clipRect.top = 0;
michael@0 1274 window.clipRect.left = 0; window.clipRect.right = 0;
michael@0 1275
michael@0 1276 // platform specific printing code
michael@0 1277 #if defined(XP_MACOSX) && !defined(__LP64__)
michael@0 1278 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
michael@0 1279 // Don't use this code if any of the QuickDraw APIs it currently requires
michael@0 1280 // are missing (as they probably will be on OS X 10.8 and up).
michael@0 1281 if (!&::SetRect || !&::NewGWorldFromPtr || !&::DisposeGWorld) {
michael@0 1282 NS_WARNING("Cannot print plugin -- required QuickDraw APIs are missing!");
michael@0 1283 return;
michael@0 1284 }
michael@0 1285
michael@0 1286 nsSize contentSize = GetContentRectRelativeToSelf().Size();
michael@0 1287 window.x = 0;
michael@0 1288 window.y = 0;
michael@0 1289 window.width = presContext->AppUnitsToDevPixels(contentSize.width);
michael@0 1290 window.height = presContext->AppUnitsToDevPixels(contentSize.height);
michael@0 1291
michael@0 1292 gfxContext *ctx = aRenderingContext.ThebesContext();
michael@0 1293 if (!ctx)
michael@0 1294 return;
michael@0 1295 gfxContextAutoSaveRestore save(ctx);
michael@0 1296
michael@0 1297 ctx->NewPath();
michael@0 1298
michael@0 1299 gfxRect rect(window.x, window.y, window.width, window.height);
michael@0 1300
michael@0 1301 ctx->Rectangle(rect);
michael@0 1302 ctx->Clip();
michael@0 1303
michael@0 1304 gfxQuartzNativeDrawing nativeDraw(ctx, rect);
michael@0 1305 CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
michael@0 1306 if (!cgContext) {
michael@0 1307 nativeDraw.EndNativeDrawing();
michael@0 1308 return;
michael@0 1309 }
michael@0 1310
michael@0 1311 window.clipRect.right = window.width;
michael@0 1312 window.clipRect.bottom = window.height;
michael@0 1313 window.type = NPWindowTypeDrawable;
michael@0 1314
michael@0 1315 ::Rect gwBounds;
michael@0 1316 ::SetRect(&gwBounds, 0, 0, window.width, window.height);
michael@0 1317
michael@0 1318 nsTArray<char> buffer(window.width * window.height * 4);
michael@0 1319 CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
michael@0 1320 if (!cspace) {
michael@0 1321 nativeDraw.EndNativeDrawing();
michael@0 1322 return;
michael@0 1323 }
michael@0 1324 CGContextRef cgBuffer =
michael@0 1325 ::CGBitmapContextCreate(buffer.Elements(),
michael@0 1326 window.width, window.height, 8, window.width * 4,
michael@0 1327 cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst);
michael@0 1328 ::CGColorSpaceRelease(cspace);
michael@0 1329 if (!cgBuffer) {
michael@0 1330 nativeDraw.EndNativeDrawing();
michael@0 1331 return;
michael@0 1332 }
michael@0 1333 GWorldPtr gWorld;
michael@0 1334 if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds,
michael@0 1335 nullptr, nullptr, 0,
michael@0 1336 buffer.Elements(), window.width * 4) != noErr) {
michael@0 1337 ::CGContextRelease(cgBuffer);
michael@0 1338 nativeDraw.EndNativeDrawing();
michael@0 1339 return;
michael@0 1340 }
michael@0 1341
michael@0 1342 window.clipRect.right = window.width;
michael@0 1343 window.clipRect.bottom = window.height;
michael@0 1344 window.type = NPWindowTypeDrawable;
michael@0 1345 // Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
michael@0 1346 // &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
michael@0 1347 // GWorldPtr isn't any kind of standard (it's not documented anywhere).
michael@0 1348 // But that's what WebKit does. And it's what the Flash plugin (apparently
michael@0 1349 // the only NPAPI plugin on OS X to support printing) seems to expect. So
michael@0 1350 // we do the same. The Flash plugin uses the CoreGraphics drawing mode.
michael@0 1351 // But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
michael@0 1352 // drawing mode. See bug 191046.
michael@0 1353 window.window = &gWorld;
michael@0 1354 npprint.print.embedPrint.platformPrint = gWorld;
michael@0 1355 npprint.print.embedPrint.window = window;
michael@0 1356 pi->Print(&npprint);
michael@0 1357
michael@0 1358 ::CGContextTranslateCTM(cgContext, 0.0f, float(window.height));
michael@0 1359 ::CGContextScaleCTM(cgContext, 1.0f, -1.0f);
michael@0 1360 CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer);
michael@0 1361 if (!image) {
michael@0 1362 ::CGContextRestoreGState(cgContext);
michael@0 1363 ::CGContextRelease(cgBuffer);
michael@0 1364 ::DisposeGWorld(gWorld);
michael@0 1365 nativeDraw.EndNativeDrawing();
michael@0 1366 return;
michael@0 1367 }
michael@0 1368 ::CGContextDrawImage(cgContext,
michael@0 1369 ::CGRectMake(0, 0, window.width, window.height),
michael@0 1370 image);
michael@0 1371 ::CGImageRelease(image);
michael@0 1372 ::CGContextRelease(cgBuffer);
michael@0 1373
michael@0 1374 ::DisposeGWorld(gWorld);
michael@0 1375
michael@0 1376 nativeDraw.EndNativeDrawing();
michael@0 1377 #pragma clang diagnostic warning "-Wdeprecated-declarations"
michael@0 1378 #elif defined(XP_UNIX)
michael@0 1379
michael@0 1380 /* XXX this just flat-out doesn't work in a thebes world --
michael@0 1381 * RenderEPS is a no-op. So don't bother to do any work here.
michael@0 1382 */
michael@0 1383 (void)window;
michael@0 1384 (void)npprint;
michael@0 1385
michael@0 1386 #elif defined(XP_WIN)
michael@0 1387
michael@0 1388 /* On Windows, we use the win32 printing surface to print. This, in
michael@0 1389 * turn, uses the Cairo paginated surface, which in turn uses the
michael@0 1390 * meta surface to record all operations and then play them back.
michael@0 1391 * This doesn't work too well for plugins, because if plugins render
michael@0 1392 * directly into the DC, the meta surface won't have any knowledge
michael@0 1393 * of them, and so at the end when it actually does the replay step,
michael@0 1394 * it'll fill the background with white and draw over whatever was
michael@0 1395 * rendered before.
michael@0 1396 *
michael@0 1397 * So, to avoid this, we use PushGroup, which creates a new windows
michael@0 1398 * surface, the plugin renders to that, and then we use normal
michael@0 1399 * cairo methods to composite that in such that it's recorded using the
michael@0 1400 * meta surface.
michael@0 1401 */
michael@0 1402
michael@0 1403 /* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
michael@0 1404 nsSize contentSize = GetContentRectRelativeToSelf().Size();
michael@0 1405 window.x = 0;
michael@0 1406 window.y = 0;
michael@0 1407 window.width = presContext->AppUnitsToDevPixels(contentSize.width);
michael@0 1408 window.height = presContext->AppUnitsToDevPixels(contentSize.height);
michael@0 1409
michael@0 1410 gfxContext *ctx = aRenderingContext.ThebesContext();
michael@0 1411
michael@0 1412 ctx->Save();
michael@0 1413
michael@0 1414 /* Make sure plugins don't do any damage outside of where they're supposed to */
michael@0 1415 ctx->NewPath();
michael@0 1416 gfxRect r(window.x, window.y, window.width, window.height);
michael@0 1417 ctx->Rectangle(r);
michael@0 1418 ctx->Clip();
michael@0 1419
michael@0 1420 gfxWindowsNativeDrawing nativeDraw(ctx, r);
michael@0 1421 do {
michael@0 1422 HDC dc = nativeDraw.BeginNativeDrawing();
michael@0 1423 if (!dc)
michael@0 1424 return;
michael@0 1425
michael@0 1426 // XXX don't we need to call nativeDraw.TransformToNativeRect here?
michael@0 1427 npprint.print.embedPrint.platformPrint = dc;
michael@0 1428 npprint.print.embedPrint.window = window;
michael@0 1429 // send off print info to plugin
michael@0 1430 pi->Print(&npprint);
michael@0 1431
michael@0 1432 nativeDraw.EndNativeDrawing();
michael@0 1433 } while (nativeDraw.ShouldRenderAgain());
michael@0 1434 nativeDraw.PaintToContext();
michael@0 1435
michael@0 1436 ctx->Restore();
michael@0 1437 #endif
michael@0 1438
michael@0 1439 // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
michael@0 1440 // XXX Calling DidReflow here makes no sense!!!
michael@0 1441 nsDidReflowStatus status = nsDidReflowStatus::FINISHED; // should we use a special status?
michael@0 1442 frame->DidReflow(presContext,
michael@0 1443 nullptr, status); // DidReflow will take care of it
michael@0 1444 }
michael@0 1445
michael@0 1446 nsRect
michael@0 1447 nsObjectFrame::GetPaintedRect(nsDisplayPlugin* aItem)
michael@0 1448 {
michael@0 1449 if (!mInstanceOwner)
michael@0 1450 return nsRect();
michael@0 1451 nsRect r = GetContentRectRelativeToSelf();
michael@0 1452 if (!mInstanceOwner->UseAsyncRendering())
michael@0 1453 return r;
michael@0 1454
michael@0 1455 nsIntSize size = mInstanceOwner->GetCurrentImageSize();
michael@0 1456 nsPresContext* pc = PresContext();
michael@0 1457 r.IntersectRect(r, nsRect(0, 0, pc->DevPixelsToAppUnits(size.width),
michael@0 1458 pc->DevPixelsToAppUnits(size.height)));
michael@0 1459 return r;
michael@0 1460 }
michael@0 1461
michael@0 1462 LayerState
michael@0 1463 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
michael@0 1464 LayerManager* aManager)
michael@0 1465 {
michael@0 1466 if (!mInstanceOwner)
michael@0 1467 return LAYER_NONE;
michael@0 1468
michael@0 1469 #ifdef MOZ_WIDGET_ANDROID
michael@0 1470 // We always want a layer on Honeycomb and later
michael@0 1471 if (AndroidBridge::Bridge()->GetAPIVersion() >= 11)
michael@0 1472 return LAYER_ACTIVE;
michael@0 1473 #endif
michael@0 1474
michael@0 1475 if (!mInstanceOwner->UseAsyncRendering()) {
michael@0 1476 return LAYER_NONE;
michael@0 1477 }
michael@0 1478
michael@0 1479 return LAYER_ACTIVE;
michael@0 1480 }
michael@0 1481
michael@0 1482 already_AddRefed<Layer>
michael@0 1483 nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
michael@0 1484 LayerManager* aManager,
michael@0 1485 nsDisplayItem* aItem,
michael@0 1486 const ContainerLayerParameters& aContainerParameters)
michael@0 1487 {
michael@0 1488 if (!mInstanceOwner)
michael@0 1489 return nullptr;
michael@0 1490
michael@0 1491 NPWindow* window = nullptr;
michael@0 1492 mInstanceOwner->GetWindow(window);
michael@0 1493 if (!window)
michael@0 1494 return nullptr;
michael@0 1495
michael@0 1496 if (window->width <= 0 || window->height <= 0)
michael@0 1497 return nullptr;
michael@0 1498
michael@0 1499 // window is in "display pixels", but size needs to be in device pixels
michael@0 1500 double scaleFactor = 1.0;
michael@0 1501 if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) {
michael@0 1502 scaleFactor = 1.0;
michael@0 1503 }
michael@0 1504 int intScaleFactor = ceil(scaleFactor);
michael@0 1505 IntSize size(window->width * intScaleFactor, window->height * intScaleFactor);
michael@0 1506
michael@0 1507 nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
michael@0 1508 gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
michael@0 1509 // to provide crisper and faster drawing.
michael@0 1510 r.Round();
michael@0 1511 nsRefPtr<Layer> layer =
michael@0 1512 (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
michael@0 1513
michael@0 1514 if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
michael@0 1515 // Create image
michael@0 1516 nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
michael@0 1517 if (!container) {
michael@0 1518 // This can occur if our instance is gone.
michael@0 1519 return nullptr;
michael@0 1520 }
michael@0 1521
michael@0 1522 if (!layer) {
michael@0 1523 mInstanceOwner->NotifyPaintWaiter(aBuilder);
michael@0 1524 // Initialize ImageLayer
michael@0 1525 layer = aManager->CreateImageLayer();
michael@0 1526 if (!layer)
michael@0 1527 return nullptr;
michael@0 1528 }
michael@0 1529
michael@0 1530 NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
michael@0 1531 ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
michael@0 1532 #ifdef XP_MACOSX
michael@0 1533 if (!mInstanceOwner->UseAsyncRendering()) {
michael@0 1534 mInstanceOwner->DoCocoaEventDrawRect(r, nullptr);
michael@0 1535 }
michael@0 1536 #endif
michael@0 1537
michael@0 1538 imglayer->SetScaleToSize(size, ScaleMode::STRETCH);
michael@0 1539 imglayer->SetContainer(container);
michael@0 1540 GraphicsFilter filter =
michael@0 1541 nsLayoutUtils::GetGraphicsFilterForFrame(this);
michael@0 1542 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
michael@0 1543 if (!aManager->IsCompositingCheap()) {
michael@0 1544 // Pixman just horrible with bilinear filter scaling
michael@0 1545 filter = GraphicsFilter::FILTER_NEAREST;
michael@0 1546 }
michael@0 1547 #endif
michael@0 1548 imglayer->SetFilter(filter);
michael@0 1549
michael@0 1550 layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
michael@0 1551 #ifdef MOZ_WIDGET_ANDROID
michael@0 1552 } else if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_VIDEO) {
michael@0 1553 nsDisplayPluginVideo* videoItem = reinterpret_cast<nsDisplayPluginVideo*>(aItem);
michael@0 1554 nsNPAPIPluginInstance::VideoInfo* videoInfo = videoItem->VideoInfo();
michael@0 1555
michael@0 1556 nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainerForVideo(videoInfo);
michael@0 1557 if (!container)
michael@0 1558 return nullptr;
michael@0 1559
michael@0 1560 if (!layer) {
michael@0 1561 // Initialize ImageLayer
michael@0 1562 layer = aManager->CreateImageLayer();
michael@0 1563 if (!layer)
michael@0 1564 return nullptr;
michael@0 1565 }
michael@0 1566
michael@0 1567 ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
michael@0 1568 imglayer->SetContainer(container);
michael@0 1569
michael@0 1570 layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
michael@0 1571
michael@0 1572 // Set the offset and size according to the video dimensions
michael@0 1573 r.MoveBy(videoInfo->mDimensions.TopLeft());
michael@0 1574 size.width = videoInfo->mDimensions.width;
michael@0 1575 size.height = videoInfo->mDimensions.height;
michael@0 1576 #endif
michael@0 1577 } else {
michael@0 1578 NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
michael@0 1579 "Unknown item type");
michael@0 1580 NS_ABORT_IF_FALSE(!IsOpaque(), "Opaque plugins don't use backgrounds");
michael@0 1581
michael@0 1582 if (!layer) {
michael@0 1583 layer = aManager->CreateReadbackLayer();
michael@0 1584 if (!layer)
michael@0 1585 return nullptr;
michael@0 1586 }
michael@0 1587 NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
michael@0 1588
michael@0 1589 ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
michael@0 1590 if (readback->GetSize() != ThebesIntSize(size)) {
michael@0 1591 // This will destroy any old background sink and notify us that the
michael@0 1592 // background is now unknown
michael@0 1593 readback->SetSink(nullptr);
michael@0 1594 readback->SetSize(ThebesIntSize(size));
michael@0 1595
michael@0 1596 if (mBackgroundSink) {
michael@0 1597 // Maybe we still have a background sink associated with another
michael@0 1598 // readback layer that wasn't recycled for some reason? Unhook it
michael@0 1599 // now so that if this frame goes away, it doesn't have a dangling
michael@0 1600 // reference to us.
michael@0 1601 mBackgroundSink->Destroy();
michael@0 1602 }
michael@0 1603 mBackgroundSink =
michael@0 1604 new PluginBackgroundSink(this,
michael@0 1605 readback->AllocateSequenceNumber());
michael@0 1606 readback->SetSink(mBackgroundSink);
michael@0 1607 // The layer has taken ownership of our sink. When either the sink dies
michael@0 1608 // or the frame dies, the connection from the surviving object is nulled out.
michael@0 1609 }
michael@0 1610 }
michael@0 1611
michael@0 1612 // Set a transform on the layer to draw the plugin in the right place
michael@0 1613 Matrix transform;
michael@0 1614 gfxPoint p = r.TopLeft() + aContainerParameters.mOffset;
michael@0 1615 transform.Translate(p.x, p.y);
michael@0 1616
michael@0 1617 layer->SetBaseTransform(Matrix4x4::From2D(transform));
michael@0 1618 layer->SetVisibleRegion(ThebesIntRect(IntRect(IntPoint(0, 0), size)));
michael@0 1619 return layer.forget();
michael@0 1620 }
michael@0 1621
michael@0 1622 void
michael@0 1623 nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
michael@0 1624 nsRenderingContext& aRenderingContext,
michael@0 1625 const nsRect& aDirtyRect, const nsRect& aPluginRect)
michael@0 1626 {
michael@0 1627 #if defined(MOZ_WIDGET_ANDROID)
michael@0 1628 if (mInstanceOwner) {
michael@0 1629 gfxRect frameGfxRect =
michael@0 1630 PresContext()->AppUnitsToGfxUnits(aPluginRect);
michael@0 1631 gfxRect dirtyGfxRect =
michael@0 1632 PresContext()->AppUnitsToGfxUnits(aDirtyRect);
michael@0 1633
michael@0 1634 gfxContext* ctx = aRenderingContext.ThebesContext();
michael@0 1635
michael@0 1636 mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
michael@0 1637 return;
michael@0 1638 }
michael@0 1639 #endif
michael@0 1640
michael@0 1641 // Screen painting code
michael@0 1642 #if defined(XP_MACOSX)
michael@0 1643 // delegate all painting to the plugin instance.
michael@0 1644 if (mInstanceOwner) {
michael@0 1645 if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics ||
michael@0 1646 mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
michael@0 1647 mInstanceOwner->GetDrawingModel() ==
michael@0 1648 NPDrawingModelInvalidatingCoreAnimation) {
michael@0 1649 int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
michael@0 1650 // Clip to the content area where the plugin should be drawn. If
michael@0 1651 // we don't do this, the plugin can draw outside its bounds.
michael@0 1652 nsIntRect contentPixels = aPluginRect.ToNearestPixels(appUnitsPerDevPixel);
michael@0 1653 nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel);
michael@0 1654 nsIntRect clipPixels;
michael@0 1655 clipPixels.IntersectRect(contentPixels, dirtyPixels);
michael@0 1656
michael@0 1657 // Don't invoke the drawing code if the clip is empty.
michael@0 1658 if (clipPixels.IsEmpty())
michael@0 1659 return;
michael@0 1660
michael@0 1661 gfxRect nativeClipRect(clipPixels.x, clipPixels.y,
michael@0 1662 clipPixels.width, clipPixels.height);
michael@0 1663 gfxContext* ctx = aRenderingContext.ThebesContext();
michael@0 1664
michael@0 1665 gfxContextAutoSaveRestore save(ctx);
michael@0 1666 ctx->NewPath();
michael@0 1667 ctx->Rectangle(nativeClipRect);
michael@0 1668 ctx->Clip();
michael@0 1669 gfxPoint offset(contentPixels.x, contentPixels.y);
michael@0 1670 ctx->Translate(offset);
michael@0 1671
michael@0 1672 gfxQuartzNativeDrawing nativeDrawing(ctx, nativeClipRect - offset);
michael@0 1673
michael@0 1674 CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
michael@0 1675 if (!cgContext) {
michael@0 1676 NS_WARNING("null CGContextRef during PaintPlugin");
michael@0 1677 return;
michael@0 1678 }
michael@0 1679
michael@0 1680 nsRefPtr<nsNPAPIPluginInstance> inst;
michael@0 1681 GetPluginInstance(getter_AddRefs(inst));
michael@0 1682 if (!inst) {
michael@0 1683 NS_WARNING("null plugin instance during PaintPlugin");
michael@0 1684 nativeDrawing.EndNativeDrawing();
michael@0 1685 return;
michael@0 1686 }
michael@0 1687 NPWindow* window;
michael@0 1688 mInstanceOwner->GetWindow(window);
michael@0 1689 if (!window) {
michael@0 1690 NS_WARNING("null plugin window during PaintPlugin");
michael@0 1691 nativeDrawing.EndNativeDrawing();
michael@0 1692 return;
michael@0 1693 }
michael@0 1694 NP_CGContext* cgPluginPortCopy =
michael@0 1695 static_cast<NP_CGContext*>(mInstanceOwner->GetPluginPortCopy());
michael@0 1696 if (!cgPluginPortCopy) {
michael@0 1697 NS_WARNING("null plugin port copy during PaintPlugin");
michael@0 1698 nativeDrawing.EndNativeDrawing();
michael@0 1699 return;
michael@0 1700 }
michael@0 1701
michael@0 1702 mInstanceOwner->BeginCGPaint();
michael@0 1703 if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
michael@0 1704 mInstanceOwner->GetDrawingModel() ==
michael@0 1705 NPDrawingModelInvalidatingCoreAnimation) {
michael@0 1706 // CoreAnimation is updated, render the layer and perform a readback.
michael@0 1707 mInstanceOwner->RenderCoreAnimation(cgContext, window->width, window->height);
michael@0 1708 } else {
michael@0 1709 mInstanceOwner->Paint(nativeClipRect - offset, cgContext);
michael@0 1710 }
michael@0 1711 mInstanceOwner->EndCGPaint();
michael@0 1712
michael@0 1713 nativeDrawing.EndNativeDrawing();
michael@0 1714 } else {
michael@0 1715 // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
michael@0 1716 nsRenderingContext::AutoPushTranslation
michael@0 1717 translate(&aRenderingContext, aPluginRect.TopLeft());
michael@0 1718
michael@0 1719 // this rect is used only in the CoreGraphics drawing model
michael@0 1720 gfxRect tmpRect(0, 0, 0, 0);
michael@0 1721 mInstanceOwner->Paint(tmpRect, nullptr);
michael@0 1722 }
michael@0 1723 }
michael@0 1724 #elif defined(MOZ_X11)
michael@0 1725 if (mInstanceOwner) {
michael@0 1726 NPWindow *window;
michael@0 1727 mInstanceOwner->GetWindow(window);
michael@0 1728 if (window->type == NPWindowTypeDrawable) {
michael@0 1729 gfxRect frameGfxRect =
michael@0 1730 PresContext()->AppUnitsToGfxUnits(aPluginRect);
michael@0 1731 gfxRect dirtyGfxRect =
michael@0 1732 PresContext()->AppUnitsToGfxUnits(aDirtyRect);
michael@0 1733 gfxContext* ctx = aRenderingContext.ThebesContext();
michael@0 1734
michael@0 1735 mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
michael@0 1736 }
michael@0 1737 }
michael@0 1738 #elif defined(XP_WIN)
michael@0 1739 nsRefPtr<nsNPAPIPluginInstance> inst;
michael@0 1740 GetPluginInstance(getter_AddRefs(inst));
michael@0 1741 if (inst) {
michael@0 1742 gfxRect frameGfxRect =
michael@0 1743 PresContext()->AppUnitsToGfxUnits(aPluginRect);
michael@0 1744 gfxRect dirtyGfxRect =
michael@0 1745 PresContext()->AppUnitsToGfxUnits(aDirtyRect);
michael@0 1746 gfxContext *ctx = aRenderingContext.ThebesContext();
michael@0 1747 gfxMatrix currentMatrix = ctx->CurrentMatrix();
michael@0 1748
michael@0 1749 if (ctx->UserToDevicePixelSnapped(frameGfxRect, false)) {
michael@0 1750 dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect);
michael@0 1751 ctx->IdentityMatrix();
michael@0 1752 }
michael@0 1753 dirtyGfxRect.RoundOut();
michael@0 1754
michael@0 1755 // Look if it's windowless
michael@0 1756 NPWindow *window;
michael@0 1757 mInstanceOwner->GetWindow(window);
michael@0 1758
michael@0 1759 if (window->type == NPWindowTypeDrawable) {
michael@0 1760 // the offset of the DC
michael@0 1761 nsPoint origin;
michael@0 1762
michael@0 1763 gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
michael@0 1764 if (nativeDraw.IsDoublePass()) {
michael@0 1765 // OOP plugin specific: let the shim know before we paint if we are doing a
michael@0 1766 // double pass render. If this plugin isn't oop, the register window message
michael@0 1767 // will be ignored.
michael@0 1768 NPEvent pluginEvent;
michael@0 1769 pluginEvent.event = plugins::DoublePassRenderingEvent();
michael@0 1770 pluginEvent.wParam = 0;
michael@0 1771 pluginEvent.lParam = 0;
michael@0 1772 if (pluginEvent.event)
michael@0 1773 inst->HandleEvent(&pluginEvent, nullptr);
michael@0 1774 }
michael@0 1775 do {
michael@0 1776 HDC hdc = nativeDraw.BeginNativeDrawing();
michael@0 1777 if (!hdc)
michael@0 1778 return;
michael@0 1779
michael@0 1780 RECT dest;
michael@0 1781 nativeDraw.TransformToNativeRect(frameGfxRect, dest);
michael@0 1782 RECT dirty;
michael@0 1783 nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty);
michael@0 1784
michael@0 1785 window->window = hdc;
michael@0 1786 window->x = dest.left;
michael@0 1787 window->y = dest.top;
michael@0 1788 window->clipRect.left = 0;
michael@0 1789 window->clipRect.top = 0;
michael@0 1790 // if we're painting, we're visible.
michael@0 1791 window->clipRect.right = window->width;
michael@0 1792 window->clipRect.bottom = window->height;
michael@0 1793
michael@0 1794 // Windowless plugins on windows need a special event to update their location,
michael@0 1795 // see bug 135737.
michael@0 1796 //
michael@0 1797 // bug 271442: note, the rectangle we send is now purely the bounds of the plugin
michael@0 1798 // relative to the window it is contained in, which is useful for the plugin to
michael@0 1799 // correctly translate mouse coordinates.
michael@0 1800 //
michael@0 1801 // this does not mesh with the comments for bug 135737 which imply that the rectangle
michael@0 1802 // must be clipped in some way to prevent the plugin attempting to paint over areas
michael@0 1803 // it shouldn't.
michael@0 1804 //
michael@0 1805 // since the two uses of the rectangle are mutually exclusive in some cases, and
michael@0 1806 // since I don't see any incorrect painting (at least with Flash and ViewPoint -
michael@0 1807 // the originator of bug 135737), it seems that windowless plugins are not relying
michael@0 1808 // on information here for clipping their drawing, and we can safely use this message
michael@0 1809 // to tell the plugin exactly where it is in all cases.
michael@0 1810
michael@0 1811 nsIntPoint origin = GetWindowOriginInPixels(true);
michael@0 1812 nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
michael@0 1813
michael@0 1814 if (!mWindowlessRect.IsEqualEdges(winlessRect)) {
michael@0 1815 mWindowlessRect = winlessRect;
michael@0 1816
michael@0 1817 WINDOWPOS winpos;
michael@0 1818 memset(&winpos, 0, sizeof(winpos));
michael@0 1819 winpos.x = mWindowlessRect.x;
michael@0 1820 winpos.y = mWindowlessRect.y;
michael@0 1821 winpos.cx = mWindowlessRect.width;
michael@0 1822 winpos.cy = mWindowlessRect.height;
michael@0 1823
michael@0 1824 // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
michael@0 1825 NPEvent pluginEvent;
michael@0 1826 pluginEvent.event = WM_WINDOWPOSCHANGED;
michael@0 1827 pluginEvent.wParam = 0;
michael@0 1828 pluginEvent.lParam = (LPARAM)&winpos;
michael@0 1829 inst->HandleEvent(&pluginEvent, nullptr);
michael@0 1830 }
michael@0 1831
michael@0 1832 inst->SetWindow(window);
michael@0 1833
michael@0 1834 mInstanceOwner->Paint(dirty, hdc);
michael@0 1835 nativeDraw.EndNativeDrawing();
michael@0 1836 } while (nativeDraw.ShouldRenderAgain());
michael@0 1837 nativeDraw.PaintToContext();
michael@0 1838 }
michael@0 1839
michael@0 1840 ctx->SetMatrix(currentMatrix);
michael@0 1841 }
michael@0 1842 #endif
michael@0 1843 }
michael@0 1844
michael@0 1845 nsresult
michael@0 1846 nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
michael@0 1847 WidgetGUIEvent* anEvent,
michael@0 1848 nsEventStatus* anEventStatus)
michael@0 1849 {
michael@0 1850 NS_ENSURE_ARG_POINTER(anEvent);
michael@0 1851 NS_ENSURE_ARG_POINTER(anEventStatus);
michael@0 1852 nsresult rv = NS_OK;
michael@0 1853
michael@0 1854 if (!mInstanceOwner)
michael@0 1855 return NS_ERROR_NULL_POINTER;
michael@0 1856
michael@0 1857 mInstanceOwner->ConsiderNewEventloopNestingLevel();
michael@0 1858
michael@0 1859 if (anEvent->message == NS_PLUGIN_ACTIVATE) {
michael@0 1860 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
michael@0 1861 nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetContent());
michael@0 1862 if (fm && elem)
michael@0 1863 return fm->SetFocus(elem, 0);
michael@0 1864 }
michael@0 1865 else if (anEvent->message == NS_PLUGIN_FOCUS) {
michael@0 1866 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
michael@0 1867 if (fm)
michael@0 1868 return fm->FocusPlugin(GetContent());
michael@0 1869 }
michael@0 1870
michael@0 1871 #ifdef XP_MACOSX
michael@0 1872 if (anEvent->message == NS_PLUGIN_RESOLUTION_CHANGED) {
michael@0 1873 double scaleFactor = 1.0;
michael@0 1874 mInstanceOwner->GetContentsScaleFactor(&scaleFactor);
michael@0 1875 mInstanceOwner->ContentsScaleFactorChanged(scaleFactor);
michael@0 1876 return NS_OK;
michael@0 1877 }
michael@0 1878 #endif
michael@0 1879
michael@0 1880 if (mInstanceOwner->SendNativeEvents() &&
michael@0 1881 anEvent->IsNativeEventDelivererForPlugin()) {
michael@0 1882 *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
michael@0 1883 // Due to plugin code reentering Gecko, this frame may be dead at this
michael@0 1884 // point.
michael@0 1885 return rv;
michael@0 1886 }
michael@0 1887
michael@0 1888 #ifdef XP_WIN
michael@0 1889 rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
michael@0 1890 return rv;
michael@0 1891 #endif
michael@0 1892
michael@0 1893 #ifdef XP_MACOSX
michael@0 1894 // we want to process some native mouse events in the cocoa event model
michael@0 1895 if ((anEvent->message == NS_MOUSE_ENTER ||
michael@0 1896 anEvent->message == NS_WHEEL_WHEEL) &&
michael@0 1897 mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
michael@0 1898 *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
michael@0 1899 // Due to plugin code reentering Gecko, this frame may be dead at this
michael@0 1900 // point.
michael@0 1901 return rv;
michael@0 1902 }
michael@0 1903
michael@0 1904 // These two calls to nsIPresShell::SetCapturingContext() (on mouse-down
michael@0 1905 // and mouse-up) are needed to make the routing of mouse events while
michael@0 1906 // dragging conform to standard OS X practice, and to the Cocoa NPAPI spec.
michael@0 1907 // See bug 525078 and bug 909678.
michael@0 1908 if (anEvent->message == NS_MOUSE_BUTTON_DOWN) {
michael@0 1909 nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
michael@0 1910 }
michael@0 1911 #endif
michael@0 1912
michael@0 1913 rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
michael@0 1914
michael@0 1915 // We need to be careful from this point because the call to
michael@0 1916 // nsObjectFrameSuper::HandleEvent() might have killed us.
michael@0 1917
michael@0 1918 #ifdef XP_MACOSX
michael@0 1919 if (anEvent->message == NS_MOUSE_BUTTON_UP) {
michael@0 1920 nsIPresShell::SetCapturingContent(nullptr, 0);
michael@0 1921 }
michael@0 1922 #endif
michael@0 1923
michael@0 1924 return rv;
michael@0 1925 }
michael@0 1926
michael@0 1927 nsresult
michael@0 1928 nsObjectFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance)
michael@0 1929 {
michael@0 1930 *aPluginInstance = nullptr;
michael@0 1931
michael@0 1932 if (!mInstanceOwner) {
michael@0 1933 return NS_OK;
michael@0 1934 }
michael@0 1935
michael@0 1936 return mInstanceOwner->GetInstance(aPluginInstance);
michael@0 1937 }
michael@0 1938
michael@0 1939 nsresult
michael@0 1940 nsObjectFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor)
michael@0 1941 {
michael@0 1942 if (!mInstanceOwner) {
michael@0 1943 return NS_ERROR_FAILURE;
michael@0 1944 }
michael@0 1945
michael@0 1946 nsRefPtr<nsNPAPIPluginInstance> inst;
michael@0 1947 mInstanceOwner->GetInstance(getter_AddRefs(inst));
michael@0 1948 if (!inst) {
michael@0 1949 return NS_ERROR_FAILURE;
michael@0 1950 }
michael@0 1951
michael@0 1952 bool useDOMCursor = static_cast<nsNPAPIPluginInstance*>(inst.get())->UsesDOMForCursor();
michael@0 1953 if (!useDOMCursor) {
michael@0 1954 return NS_ERROR_FAILURE;
michael@0 1955 }
michael@0 1956
michael@0 1957 return nsObjectFrameSuper::GetCursor(aPoint, aCursor);
michael@0 1958 }
michael@0 1959
michael@0 1960 void
michael@0 1961 nsObjectFrame::SetIsDocumentActive(bool aIsActive)
michael@0 1962 {
michael@0 1963 #ifndef XP_MACOSX
michael@0 1964 if (mInstanceOwner) {
michael@0 1965 mInstanceOwner->UpdateDocumentActiveState(aIsActive);
michael@0 1966 }
michael@0 1967 #endif
michael@0 1968 }
michael@0 1969
michael@0 1970 // static
michael@0 1971 nsIObjectFrame *
michael@0 1972 nsObjectFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
michael@0 1973 {
michael@0 1974 nsIFrame* child = aRoot->GetFirstPrincipalChild();
michael@0 1975
michael@0 1976 while (child) {
michael@0 1977 nsIObjectFrame* outFrame = do_QueryFrame(child);
michael@0 1978 if (outFrame) {
michael@0 1979 nsRefPtr<nsNPAPIPluginInstance> pi;
michael@0 1980 outFrame->GetPluginInstance(getter_AddRefs(pi)); // make sure we have a REAL plugin
michael@0 1981 if (pi)
michael@0 1982 return outFrame;
michael@0 1983 }
michael@0 1984
michael@0 1985 outFrame = GetNextObjectFrame(aPresContext, child);
michael@0 1986 if (outFrame)
michael@0 1987 return outFrame;
michael@0 1988 child = child->GetNextSibling();
michael@0 1989 }
michael@0 1990
michael@0 1991 return nullptr;
michael@0 1992 }
michael@0 1993
michael@0 1994 /*static*/ void
michael@0 1995 nsObjectFrame::BeginSwapDocShells(nsIContent* aContent, void*)
michael@0 1996 {
michael@0 1997 NS_PRECONDITION(aContent, "");
michael@0 1998
michael@0 1999 // This function is called from a document content enumerator so we need
michael@0 2000 // to filter out the nsObjectFrames and ignore the rest.
michael@0 2001 nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame());
michael@0 2002 if (!obj)
michael@0 2003 return;
michael@0 2004
michael@0 2005 nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj);
michael@0 2006 NS_ASSERTION(!objectFrame->mWidget || objectFrame->mWidget->GetParent(),
michael@0 2007 "Plugin windows must not be toplevel");
michael@0 2008 objectFrame->UnregisterPluginForGeometryUpdates();
michael@0 2009 }
michael@0 2010
michael@0 2011 /*static*/ void
michael@0 2012 nsObjectFrame::EndSwapDocShells(nsIContent* aContent, void*)
michael@0 2013 {
michael@0 2014 NS_PRECONDITION(aContent, "");
michael@0 2015
michael@0 2016 // This function is called from a document content enumerator so we need
michael@0 2017 // to filter out the nsObjectFrames and ignore the rest.
michael@0 2018 nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame());
michael@0 2019 if (!obj)
michael@0 2020 return;
michael@0 2021
michael@0 2022 nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj);
michael@0 2023 nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext();
michael@0 2024 NS_ASSERTION(rootPC, "unable to register the plugin frame");
michael@0 2025 nsIWidget* widget = objectFrame->mWidget;
michael@0 2026 if (widget) {
michael@0 2027 // Reparent the widget.
michael@0 2028 nsIWidget* parent =
michael@0 2029 rootPC->PresShell()->GetRootFrame()->GetNearestWidget();
michael@0 2030 widget->SetParent(parent);
michael@0 2031 nsWeakFrame weakFrame(objectFrame);
michael@0 2032 objectFrame->CallSetWindow();
michael@0 2033 if (!weakFrame.IsAlive()) {
michael@0 2034 return;
michael@0 2035 }
michael@0 2036 }
michael@0 2037
michael@0 2038 #ifdef XP_MACOSX
michael@0 2039 if (objectFrame->mWidget) {
michael@0 2040 objectFrame->RegisterPluginForGeometryUpdates();
michael@0 2041 }
michael@0 2042 #else
michael@0 2043 objectFrame->RegisterPluginForGeometryUpdates();
michael@0 2044 #endif
michael@0 2045 }
michael@0 2046
michael@0 2047 nsIFrame*
michael@0 2048 NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
michael@0 2049 {
michael@0 2050 return new (aPresShell) nsObjectFrame(aContext);
michael@0 2051 }
michael@0 2052
michael@0 2053 bool
michael@0 2054 nsObjectFrame::IsPaintedByGecko() const
michael@0 2055 {
michael@0 2056 #ifdef XP_MACOSX
michael@0 2057 return true;
michael@0 2058 #else
michael@0 2059 return !mWidget;
michael@0 2060 #endif
michael@0 2061 }
michael@0 2062
michael@0 2063 NS_IMPL_FRAMEARENA_HELPERS(nsObjectFrame)

mercurial