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