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"
14 // This is needed for DoublePassRenderingEvent.
15 #include "mozilla/plugins/PluginMessageUtils.h"
20 #include "nsPresContext.h"
21 #include "nsIPresShell.h"
22 #include "nsWidgetsCID.h"
24 #include "nsViewManager.h"
26 #include "nsGkAtoms.h"
27 #include "nsIPluginInstanceOwner.h"
28 #include "nsNPAPIPluginInstance.h"
29 #include "nsIDOMElement.h"
30 #include "nsRenderingContext.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"
42 #include "nsIObjectFrame.h"
43 #include "nsPluginNativeWindow.h"
44 #include "FrameLayerBuilder.h"
46 #include "ImageLayers.h"
47 #include "nsPluginInstanceOwner.h"
50 #include "gfxWindowsNativeDrawing.h"
51 #include "gfxWindowsSurface.h"
55 #include "ReadbackLayer.h"
56 #include "ImageContainer.h"
58 // accessibility support
60 #include "nsAccessibilityService.h"
64 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
65 #endif /* MOZ_LOGGING */
69 #include "gfxQuartzNativeDrawing.h"
70 #include "nsPluginUtilsOSX.h"
71 #include "mozilla/gfx/QuartzSupport.h"
75 #include "mozilla/X11Util.h"
76 using mozilla::DefaultXDisplay
;
84 #ifdef MOZ_WIDGET_ANDROID
85 #include "AndroidBridge.h"
86 #include "GLContext.h"
89 #ifdef CreateEvent // Thank you MS.
94 static PRLogModuleInfo
*
97 static PRLogModuleInfo
*sLog
;
99 sLog
= PR_NewLogModule("nsObjectFrame");
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.
113 #if !defined(__QUICKDRAWAPI__)
120 __attribute__((weak_import
));
121 #endif /* __QUICKDRAWAPI__ */
123 #if !defined(__QDOFFSCREEN__)
124 extern QDErr
NewGWorldFromPtr(
125 GWorldPtr
* offscreenGWorld
,
127 const Rect
* boundsRect
,
128 CTabHandle cTable
, /* can be nullptr */
129 GDHandle aGDevice
, /* can be nullptr */
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
{
147 PluginBackgroundSink(nsObjectFrame
* aFrame
, uint64_t aStartSequenceNumber
)
148 : mLastSequenceNumber(aStartSequenceNumber
), mFrame(aFrame
) {}
149 ~PluginBackgroundSink()
152 mFrame
->mBackgroundSink
= nullptr;
156 virtual void SetUnknown(uint64_t aSequenceNumber
)
158 if (!AcceptUpdate(aSequenceNumber
))
160 mFrame
->mInstanceOwner
->SetBackgroundUnknown();
163 virtual already_AddRefed
<gfxContext
>
164 BeginUpdate(const nsIntRect
& aRect
, uint64_t aSequenceNumber
)
166 if (!AcceptUpdate(aSequenceNumber
))
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; }
179 bool AcceptUpdate(uint64_t aSequenceNumber
) {
180 if (aSequenceNumber
> mLastSequenceNumber
&& mFrame
&&
181 mFrame
->mInstanceOwner
) {
182 mLastSequenceNumber
= aSequenceNumber
;
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
)
213 nsObjectFrame::AccessibleType()
215 return a11y::ePluginType
;
219 NS_IMETHODIMP
nsObjectFrame::GetPluginPort(HWND
*aPort
)
221 *aPort
= (HWND
) mInstanceOwner
->GetPluginPortFromWidget();
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
);
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
252 if (mInstanceOwner
) {
253 mInstanceOwner
->SetFrame(nullptr);
255 objContent
->HasNewFrame(nullptr);
257 if (mBackgroundSink
) {
258 mBackgroundSink
->Destroy();
261 nsObjectFrameSuper::DestroyFrom(aDestructRoot
);
265 nsObjectFrame::DidSetStyleContext(nsStyleContext
* aOldStyleContext
)
268 nsView
* view
= GetView();
269 nsViewManager
* vm
= view
->GetViewManager();
271 nsViewVisibility visibility
=
272 IsHidden() ? nsViewVisibility_kHide
: nsViewVisibility_kShow
;
273 vm
->SetViewVisibility(view
, visibility
);
277 nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext
);
281 nsObjectFrame::GetType() const
283 return nsGkAtoms::objectFrame
;
286 #ifdef DEBUG_FRAME_DUMP
288 nsObjectFrame::GetFrameName(nsAString
& aResult
) const
290 return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult
);
295 nsObjectFrame::PrepForDrawing(nsIWidget
*aWidget
)
299 nsView
* view
= GetView();
300 NS_ASSERTION(view
, "Object frames must have views");
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
;
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();
325 return NS_ERROR_FAILURE
;
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
);
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
);
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
);
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()) {
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()) {
380 frame
->GetVisitedDependentColor(eCSSProperty_background_color
);
381 if (NS_GET_A(bgcolor
) > 0) { // make sure we got an actual color
382 mWidget
->SetBackgroundColor(bgcolor
);
387 // Changing to windowless mode changes the NPWindow geometry.
388 FixupWindow(GetContentRectRelativeToSelf().Size());
391 RegisterPluginForGeometryUpdates();
396 viewMan
->SetViewVisibility(view
, nsViewVisibility_kShow
);
400 nsAccessibilityService
* accService
= nsIPresShell::AccService();
402 accService
->RecreateAccessible(PresContext()->PresShell(), mContent
);
409 #define EMBED_DEF_WIDTH 240
410 #define EMBED_DEF_HEIGHT 200
412 /* virtual */ nscoord
413 nsObjectFrame::GetMinISize(nsRenderingContext
*aRenderingContext
)
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
);
428 /* virtual */ nscoord
429 nsObjectFrame::GetPrefISize(nsRenderingContext
*aRenderingContext
)
431 return nsObjectFrame::GetMinISize(aRenderingContext
);
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)) {
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());
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).
476 if (aMetrics
.Width() == NS_UNCONSTRAINEDSIZE
) {
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
) {
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.
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
;
521 // if we are printing or print previewing, bail for now
522 if (aPresContext
->Medium() == nsGkAtoms::print
) {
523 aStatus
= NS_FRAME_COMPLETE
;
527 nsRect
r(0, 0, aMetrics
.Width(), aMetrics
.Height());
528 r
.Deflate(aReflowState
.ComputedPhysicalBorderPadding());
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 ///////////////
550 nsObjectFrame::ReflowFinished()
552 mReflowCallbackPosted
= false;
558 nsObjectFrame::ReflowCallbackCanceled()
560 mReflowCallbackPosted
= false;
564 nsObjectFrame::FixupWindow(const nsSize
& aSize
)
566 nsPresContext
* presContext
= PresContext();
572 mInstanceOwner
->GetWindow(window
);
574 NS_ENSURE_TRUE_VOID(window
);
577 nsWeakFrame
weakFrame(this);
578 mInstanceOwner
->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable
);
579 if (!weakFrame
.IsAlive()) {
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
))) {
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.
603 window
->clipRect
.top
= 0;
604 window
->clipRect
.left
= 0;
605 window
->clipRect
.bottom
= 0;
606 window
->clipRect
.right
= 0;
608 mInstanceOwner
->UpdateWindowPositionAndClipRect(false);
611 NotifyPluginReflowObservers();
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
))) ||
624 NS_FAILED(rv
= mInstanceOwner
->GetWindow(win
)) ||
628 nsPluginNativeWindow
*window
= (nsPluginNativeWindow
*)win
;
630 nsWeakFrame
weakFrame(this);
631 mInstanceOwner
->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable
);
632 if (!weakFrame
.IsAlive()) {
633 return NS_ERROR_NOT_AVAILABLE
;
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();
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
))) {
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
);
676 rv
= window
->CallSetWindow(pi
);
679 instanceOwnerRef
->ReleasePluginPort(window
->window
);
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...
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
);
704 nsObjectFrame::UnregisterPluginForGeometryUpdates()
706 if (!mRootPresContextRegisteredWith
) {
710 mRootPresContextRegisteredWith
->UnregisterPluginForGeometryUpdates(mContent
);
711 mRootPresContextRegisteredWith
= nullptr;
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
) {
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();
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);
745 nsObjectFrame::IsFocusable(int32_t *aTabIndex
, bool aWithMouse
)
749 return nsObjectFrameSuper::IsFocusable(aTabIndex
, aWithMouse
);
753 nsObjectFrame::IsHidden(bool aCheckVisibilityStyle
) const
755 if (aCheckVisibilityStyle
) {
756 if (!StyleVisibility()->IsVisibleOrCollapsed())
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
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.
770 if (mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::hidden
, hidden
) &&
772 (!hidden
.LowerCaseEqualsLiteral("false") &&
773 !hidden
.LowerCaseEqualsLiteral("no") &&
774 !hidden
.LowerCaseEqualsLiteral("off")))) {
782 nsIntPoint
nsObjectFrame::GetWindowOriginInPixels(bool aWindowless
)
784 nsView
* parentWithView
;
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
));
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
)
824 nsView
* view
= GetView();
825 nsViewManager
* vm
= view
->GetViewManager();
827 vm
->SetViewVisibility(view
, IsHidden() ? nsViewVisibility_kHide
: nsViewVisibility_kShow
);
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
{
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
);
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
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();
888 nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
)
891 return GetDisplayItemBounds(aBuilder
, this, mFrame
);
894 #ifdef MOZ_WIDGET_ANDROID
896 class nsDisplayPluginVideo
: public nsDisplayItem
{
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
);
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
928 nsNPAPIPluginInstance::VideoInfo
* VideoInfo() { return mVideoInfo
; }
931 nsNPAPIPluginInstance::VideoInfo
* mVideoInfo
;
935 nsDisplayPluginVideo::GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
)
938 return GetDisplayItemBounds(aBuilder
, this, mFrame
);
944 nsDisplayPlugin::GetBounds(nsDisplayListBuilder
* aBuilder
, bool* aSnap
)
947 return GetDisplayItemBounds(aBuilder
, this, mFrame
);
951 nsDisplayPlugin::Paint(nsDisplayListBuilder
* aBuilder
,
952 nsRenderingContext
* aCtx
)
954 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(mFrame
);
956 f
->PaintPlugin(aBuilder
, *aCtx
, mVisibleRect
, GetBounds(aBuilder
, &snap
));
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()) {
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
);
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
);
1004 nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
1009 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(mFrame
);
1010 if (!aBuilder
->IsForPluginGeometry()) {
1011 nsIWidget
* widget
= f
->GetWidget();
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.
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
1038 nsObjectFrame::PluginEventNotifier::Run() {
1039 nsCOMPtr
<nsIObserverService
> obsSvc
=
1040 mozilla::services::GetObserverService();
1041 obsSvc
->NotifyObservers(nullptr, "plugin-changed-event", mEventType
.get());
1046 nsObjectFrame::NotifyPluginReflowObservers()
1048 nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
1052 nsObjectFrame::DidSetWidgetGeometry()
1054 #if defined(XP_MACOSX)
1055 if (mInstanceOwner
) {
1056 mInstanceOwner
->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable
);
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
1065 mInstanceOwner
->UpdateWindowVisibility(
1066 nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
1067 !mNextConfigurationBounds
.IsEmpty());
1073 nsObjectFrame::IsOpaque() const
1075 #if defined(XP_MACOSX)
1078 #elif defined(MOZ_WIDGET_ANDROID)
1079 // We don't know, so just assume transparent
1082 return !IsTransparentMode();
1087 nsObjectFrame::IsTransparentMode() const
1089 #if defined(XP_MACOSX)
1093 if (!mInstanceOwner
)
1096 NPWindow
*window
= nullptr;
1097 mInstanceOwner
->GetWindow(window
);
1102 if (window
->type
!= NPWindowTypeDrawable
)
1106 nsRefPtr
<nsNPAPIPluginInstance
> pi
;
1107 rv
= mInstanceOwner
->GetInstance(getter_AddRefs(pi
));
1108 if (NS_FAILED(rv
) || !pi
)
1111 bool transparent
= false;
1112 pi
->IsTransparent(&transparent
);
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
))
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
)
1134 DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame");
1137 if (mWidget
&& aBuilder
->IsInTransform()) {
1138 // Windowed plugins should not be rendered inside a transform.
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()) {
1149 mInstanceOwner
->UpdateWindowVisibility(true);
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
));
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));
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
]));
1194 aLists
.Content()->AppendNewToTop(new (aBuilder
)
1195 nsDisplayPlugin(aBuilder
, this));
1200 nsObjectFrame::PrintPlugin(nsRenderingContext
& aRenderingContext
,
1201 const nsRect
& aDirtyRect
)
1203 nsCOMPtr
<nsIObjectLoadingContent
> obj(do_QueryInterface(mContent
));
1207 nsIFrame
* frame
= nullptr;
1208 obj
->GetPrintFrame(&frame
);
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
);
1217 objectFrame
= GetNextObjectFrame(presContext
,frame
);
1221 // finally we can get our plugin instance
1222 nsRefPtr
<nsNPAPIPluginInstance
> pi
;
1223 if (NS_FAILED(objectFrame
->GetPluginInstance(getter_AddRefs(pi
))) || !pi
)
1226 // now we need to setup the correct location for printing
1228 window
.window
= nullptr;
1230 // prepare embedded mode printing struct
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!");
1252 nsSize contentSize
= GetContentRectRelativeToSelf().Size();
1255 window
.width
= presContext
->AppUnitsToDevPixels(contentSize
.width
);
1256 window
.height
= presContext
->AppUnitsToDevPixels(contentSize
.height
);
1258 gfxContext
*ctx
= aRenderingContext
.ThebesContext();
1261 gfxContextAutoSaveRestore
save(ctx
);
1265 gfxRect
rect(window
.x
, window
.y
, window
.width
, window
.height
);
1267 ctx
->Rectangle(rect
);
1270 gfxQuartzNativeDrawing
nativeDraw(ctx
, rect
);
1271 CGContextRef cgContext
= nativeDraw
.BeginNativeDrawing();
1273 nativeDraw
.EndNativeDrawing();
1277 window
.clipRect
.right
= window
.width
;
1278 window
.clipRect
.bottom
= window
.height
;
1279 window
.type
= NPWindowTypeDrawable
;
1282 ::SetRect(&gwBounds
, 0, 0, window
.width
, window
.height
);
1284 nsTArray
<char> buffer(window
.width
* window
.height
* 4);
1285 CGColorSpaceRef cspace
= ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB
);
1287 nativeDraw
.EndNativeDrawing();
1290 CGContextRef cgBuffer
=
1291 ::CGBitmapContextCreate(buffer
.Elements(),
1292 window
.width
, window
.height
, 8, window
.width
* 4,
1293 cspace
, kCGBitmapByteOrder32Big
| kCGImageAlphaPremultipliedFirst
);
1294 ::CGColorSpaceRelease(cspace
);
1296 nativeDraw
.EndNativeDrawing();
1300 if (::NewGWorldFromPtr(&gWorld
, k32ARGBPixelFormat
, &gwBounds
,
1301 nullptr, nullptr, 0,
1302 buffer
.Elements(), window
.width
* 4) != noErr
) {
1303 ::CGContextRelease(cgBuffer
);
1304 nativeDraw
.EndNativeDrawing();
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
);
1328 ::CGContextRestoreGState(cgContext
);
1329 ::CGContextRelease(cgBuffer
);
1330 ::DisposeGWorld(gWorld
);
1331 nativeDraw
.EndNativeDrawing();
1334 ::CGContextDrawImage(cgContext
,
1335 ::CGRectMake(0, 0, window
.width
, window
.height
),
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.
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
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
1369 /* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
1370 nsSize contentSize
= GetContentRectRelativeToSelf().Size();
1373 window
.width
= presContext
->AppUnitsToDevPixels(contentSize
.width
);
1374 window
.height
= presContext
->AppUnitsToDevPixels(contentSize
.height
);
1376 gfxContext
*ctx
= aRenderingContext
.ThebesContext();
1380 /* Make sure plugins don't do any damage outside of where they're supposed to */
1382 gfxRect
r(window
.x
, window
.y
, window
.width
, window
.height
);
1386 gfxWindowsNativeDrawing
nativeDraw(ctx
, r
);
1388 HDC dc
= nativeDraw
.BeginNativeDrawing();
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();
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
1413 nsObjectFrame::GetPaintedRect(nsDisplayPlugin
* aItem
)
1415 if (!mInstanceOwner
)
1417 nsRect r
= GetContentRectRelativeToSelf();
1418 if (!mInstanceOwner
->UseAsyncRendering())
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
)));
1429 nsObjectFrame::GetLayerState(nsDisplayListBuilder
* aBuilder
,
1430 LayerManager
* aManager
)
1432 if (!mInstanceOwner
)
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
;
1441 if (!mInstanceOwner
->UseAsyncRendering()) {
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
)
1457 NPWindow
* window
= nullptr;
1458 mInstanceOwner
->GetWindow(window
);
1462 if (window
->width
<= 0 || window
->height
<= 0)
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
))) {
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.
1477 nsRefPtr
<Layer
> layer
=
1478 (aManager
->GetLayerBuilder()->GetLeafLayerFor(aBuilder
, aItem
));
1480 if (aItem
->GetType() == nsDisplayItem::TYPE_PLUGIN
) {
1482 nsRefPtr
<ImageContainer
> container
= mInstanceOwner
->GetImageContainer();
1484 // This can occur if our instance is gone.
1489 mInstanceOwner
->NotifyPaintWaiter(aBuilder
);
1490 // Initialize ImageLayer
1491 layer
= aManager
->CreateImageLayer();
1496 NS_ASSERTION(layer
->GetType() == Layer::TYPE_IMAGE
, "Bad layer type");
1497 ImageLayer
* imglayer
= static_cast<ImageLayer
*>(layer
.get());
1499 if (!mInstanceOwner
->UseAsyncRendering()) {
1500 mInstanceOwner
->DoCocoaEventDrawRect(r
, nullptr);
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
;
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
);
1527 // Initialize ImageLayer
1528 layer
= aManager
->CreateImageLayer();
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
;
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");
1549 layer
= aManager
->CreateReadbackLayer();
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
1567 mBackgroundSink
->Destroy();
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
1580 gfxPoint p
= r
.TopLeft() + aContainerParameters
.mOffset
;
1581 transform
.Translate(p
.x
, p
.y
);
1583 layer
->SetBaseTransform(Matrix4x4::From2D(transform
));
1584 return layer
.forget();
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
);
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())
1626 gfxRect
nativeClipRect(clipPixels
.x
, clipPixels
.y
,
1627 clipPixels
.width
, clipPixels
.height
);
1628 gfxContext
* ctx
= aRenderingContext
.ThebesContext();
1630 gfxContextAutoSaveRestore
save(ctx
);
1632 ctx
->Rectangle(nativeClipRect
);
1634 gfxPoint
offset(contentPixels
.x
, contentPixels
.y
);
1635 ctx
->Translate(offset
);
1637 gfxQuartzNativeDrawing
nativeDrawing(ctx
, nativeClipRect
- offset
);
1639 CGContextRef cgContext
= nativeDrawing
.BeginNativeDrawing();
1641 NS_WARNING("null CGContextRef during PaintPlugin");
1645 nsRefPtr
<nsNPAPIPluginInstance
> inst
;
1646 GetPluginInstance(getter_AddRefs(inst
));
1648 NS_WARNING("null plugin instance during PaintPlugin");
1649 nativeDrawing
.EndNativeDrawing();
1653 mInstanceOwner
->GetWindow(window
);
1655 NS_WARNING("null plugin window during PaintPlugin");
1656 nativeDrawing
.EndNativeDrawing();
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();
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
);
1674 mInstanceOwner
->Paint(nativeClipRect
- offset
, cgContext
);
1676 mInstanceOwner
->EndCGPaint();
1678 nativeDrawing
.EndNativeDrawing();
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
) {
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
));
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
1722 mInstanceOwner
->GetWindow(window
);
1724 if (window
->type
== NPWindowTypeDrawable
) {
1725 // the offset of the DC
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
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);
1741 HDC hdc
= nativeDraw
.BeginNativeDrawing();
1746 nativeDraw
.TransformToNativeRect(frameGfxRect
, dest
);
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,
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
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
;
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
);
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());
1828 return fm
->SetFocus(elem
, 0);
1830 else if (anEvent
->message
== NS_PLUGIN_FOCUS
) {
1831 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
1833 return fm
->FocusPlugin(GetContent());
1837 if (anEvent
->message
== NS_PLUGIN_RESOLUTION_CHANGED
) {
1838 double scaleFactor
= 1.0;
1839 mInstanceOwner
->GetContentsScaleFactor(&scaleFactor
);
1840 mInstanceOwner
->ContentsScaleFactorChanged(scaleFactor
);
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
1854 rv
= nsObjectFrameSuper::HandleEvent(aPresContext
, anEvent
, anEventStatus
);
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
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
);
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.
1884 if (anEvent
->message
== NS_MOUSE_BUTTON_UP
) {
1885 nsIPresShell::SetCapturingContent(nullptr, 0);
1893 nsObjectFrame::GetPluginInstance(nsNPAPIPluginInstance
** aPluginInstance
)
1895 *aPluginInstance
= nullptr;
1897 if (!mInstanceOwner
) {
1901 return mInstanceOwner
->GetInstance(aPluginInstance
);
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
));
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
);
1926 nsObjectFrame::SetIsDocumentActive(bool aIsActive
)
1929 if (mInstanceOwner
) {
1930 mInstanceOwner
->UpdateDocumentActiveState(aIsActive
);
1937 nsObjectFrame::GetNextObjectFrame(nsPresContext
* aPresContext
, nsIFrame
* aRoot
)
1939 nsIFrame
* child
= aRoot
->GetFirstPrincipalChild();
1942 nsIObjectFrame
* outFrame
= do_QueryFrame(child
);
1944 nsRefPtr
<nsNPAPIPluginInstance
> pi
;
1945 outFrame
->GetPluginInstance(getter_AddRefs(pi
)); // make sure we have a REAL plugin
1950 outFrame
= GetNextObjectFrame(aPresContext
, child
);
1953 child
= child
->GetNextSibling();
1960 nsObjectFrame::BeginSwapDocShells(nsISupports
* aSupports
, void*)
1962 NS_PRECONDITION(aSupports
, "");
1963 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aSupports
));
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());
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();
1981 nsObjectFrame::EndSwapDocShells(nsISupports
* aSupports
, void*)
1983 NS_PRECONDITION(aSupports
, "");
1984 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aSupports
));
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());
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
;
2000 // Reparent the widget.
2002 rootPC
->PresShell()->GetRootFrame()->GetNearestWidget();
2003 widget
->SetParent(parent
);
2004 nsWeakFrame
weakFrame(objectFrame
);
2005 objectFrame
->CallSetWindow();
2006 if (!weakFrame
.IsAlive()) {
2012 if (objectFrame
->mWidget
) {
2013 objectFrame
->RegisterPluginForGeometryUpdates();
2016 objectFrame
->RegisterPluginForGeometryUpdates();
2021 NS_NewObjectFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
2023 return new (aPresShell
) nsObjectFrame(aContext
);
2027 nsObjectFrame::IsPaintedByGecko() const
2036 NS_IMPL_FRAMEARENA_HELPERS(nsObjectFrame
)