michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* rendering objects for replaced elements implemented by a plugin */ michael@0: michael@0: #ifndef nsObjectFrame_h___ michael@0: #define nsObjectFrame_h___ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsIObjectFrame.h" michael@0: #include "nsFrame.h" michael@0: #include "nsRegion.h" michael@0: #include "nsDisplayList.h" michael@0: #include "nsIReflowCallback.h" michael@0: michael@0: #ifdef XP_WIN michael@0: #include // For HWND :( michael@0: #endif michael@0: michael@0: class nsPresContext; michael@0: class nsRootPresContext; michael@0: class nsDisplayPlugin; michael@0: class nsIOSurface; michael@0: class PluginBackgroundSink; michael@0: class nsPluginInstanceOwner; michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: class ImageContainer; michael@0: class Layer; michael@0: class LayerManager; michael@0: } michael@0: } michael@0: michael@0: typedef nsFrame nsObjectFrameSuper; michael@0: michael@0: class nsObjectFrame : public nsObjectFrameSuper, michael@0: public nsIObjectFrame, michael@0: public nsIReflowCallback { michael@0: public: michael@0: typedef mozilla::LayerState LayerState; michael@0: typedef mozilla::layers::Layer Layer; michael@0: typedef mozilla::layers::LayerManager LayerManager; michael@0: typedef mozilla::layers::ImageContainer ImageContainer; michael@0: typedef mozilla::ContainerLayerParameters ContainerLayerParameters; michael@0: michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: friend nsIFrame* NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); michael@0: michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_QUERYFRAME_TARGET(nsObjectFrame) michael@0: michael@0: virtual void Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; michael@0: virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: virtual nsresult DidReflow(nsPresContext* aPresContext, michael@0: const nsHTMLReflowState* aReflowState, michael@0: nsDidReflowStatus aStatus) MOZ_OVERRIDE; michael@0: virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult HandleEvent(nsPresContext* aPresContext, michael@0: mozilla::WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) MOZ_OVERRIDE; michael@0: michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: michael@0: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE michael@0: { michael@0: return nsObjectFrameSuper::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced)); michael@0: } michael@0: michael@0: virtual bool NeedsView() MOZ_OVERRIDE { return true; } michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: michael@0: virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; michael@0: michael@0: NS_METHOD GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance) MOZ_OVERRIDE; michael@0: michael@0: virtual void SetIsDocumentActive(bool aIsActive) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult GetCursor(const nsPoint& aPoint, michael@0: nsIFrame::Cursor& aCursor) MOZ_OVERRIDE; michael@0: michael@0: // APIs used by nsRootPresContext to set up the widget position/size/clip michael@0: // region. michael@0: /** michael@0: * Set the next widget configuration for the plugin to the desired michael@0: * position of the plugin's widget, on the assumption that it is not visible michael@0: * (clipped out or covered by opaque content). michael@0: * This will only be called for plugins which have been registered michael@0: * with the root pres context for geometry updates. michael@0: * If there is no widget associated with the plugin, this will have no effect. michael@0: */ michael@0: void SetEmptyWidgetConfiguration() michael@0: { michael@0: mNextConfigurationBounds = nsIntRect(0,0,0,0); michael@0: mNextConfigurationClipRegion.Clear(); michael@0: } michael@0: /** michael@0: * Append the desired widget configuration to aConfigurations. michael@0: */ michael@0: void GetWidgetConfiguration(nsTArray* aConfigurations) michael@0: { michael@0: if (mWidget) { michael@0: if (!mWidget->GetParent()) { michael@0: // Plugin widgets should not be toplevel except when they're out of the michael@0: // document, in which case the plugin should not be registered for michael@0: // geometry updates and this should not be called. But apparently we michael@0: // have bugs where mWidget sometimes is toplevel here. Bail out. michael@0: NS_ERROR("Plugin widgets registered for geometry updates should not be toplevel"); michael@0: return; michael@0: } michael@0: nsIWidget::Configuration* configuration = aConfigurations->AppendElement(); michael@0: configuration->mChild = mWidget; michael@0: configuration->mBounds = mNextConfigurationBounds; michael@0: configuration->mClipRegion = mNextConfigurationClipRegion; michael@0: } michael@0: } michael@0: /** michael@0: * Called after all widget position/size/clip regions have been changed michael@0: * (even if there isn't a widget for this plugin). michael@0: */ michael@0: void DidSetWidgetGeometry(); michael@0: michael@0: // accessibility support michael@0: #ifdef ACCESSIBILITY michael@0: virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; michael@0: #ifdef XP_WIN michael@0: NS_IMETHOD GetPluginPort(HWND *aPort); michael@0: #endif michael@0: #endif michael@0: michael@0: //local methods michael@0: nsresult PrepForDrawing(nsIWidget *aWidget); michael@0: michael@0: // for a given aRoot, this walks the frame tree looking for the next outFrame michael@0: static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext, michael@0: nsIFrame* aRoot); michael@0: michael@0: // nsIReflowCallback michael@0: virtual bool ReflowFinished() MOZ_OVERRIDE; michael@0: virtual void ReflowCallbackCanceled() MOZ_OVERRIDE; michael@0: michael@0: /** michael@0: * Builds either an ImageLayer or a ReadbackLayer, depending on the type michael@0: * of aItem (TYPE_PLUGIN or TYPE_PLUGIN_READBACK respectively). michael@0: */ michael@0: already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, michael@0: LayerManager* aManager, michael@0: nsDisplayItem* aItem, michael@0: const ContainerLayerParameters& aContainerParameters); michael@0: michael@0: LayerState GetLayerState(nsDisplayListBuilder* aBuilder, michael@0: LayerManager* aManager); michael@0: michael@0: /** michael@0: * Get the rectangle (relative to this frame) which it will paint. Normally michael@0: * the frame's content-box but may be smaller if the plugin is rendering michael@0: * asynchronously and has a different-sized image temporarily. michael@0: */ michael@0: nsRect GetPaintedRect(nsDisplayPlugin* aItem); michael@0: michael@0: /** michael@0: * If aContent has a nsObjectFrame, then prepare it for a DocShell swap. michael@0: * @see nsSubDocumentFrame::BeginSwapDocShells. michael@0: * There will be a call to EndSwapDocShells after we were moved to the michael@0: * new view tree. michael@0: */ michael@0: static void BeginSwapDocShells(nsIContent* aContent, void*); michael@0: /** michael@0: * If aContent has a nsObjectFrame, then set it up after a DocShell swap. michael@0: * @see nsSubDocumentFrame::EndSwapDocShells. michael@0: */ michael@0: static void EndSwapDocShells(nsIContent* aContent, void*); michael@0: michael@0: nsIWidget* GetWidget() MOZ_OVERRIDE { return mInnerView ? mWidget : nullptr; } michael@0: michael@0: /** michael@0: * Adjust the plugin's idea of its size, using aSize as its new size. michael@0: * (aSize must be in twips) michael@0: */ michael@0: void FixupWindow(const nsSize& aSize); michael@0: michael@0: /* michael@0: * Sets up the plugin window and calls SetWindow on the plugin. michael@0: */ michael@0: nsresult CallSetWindow(bool aCheckIsHidden = true); michael@0: michael@0: void SetInstanceOwner(nsPluginInstanceOwner* aOwner); michael@0: michael@0: protected: michael@0: nsObjectFrame(nsStyleContext* aContext); michael@0: virtual ~nsObjectFrame(); michael@0: michael@0: // NOTE: This frame class does not inherit from |nsLeafFrame|, so michael@0: // this is not a virtual method implementation. michael@0: void GetDesiredSize(nsPresContext* aPresContext, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsHTMLReflowMetrics& aDesiredSize); michael@0: michael@0: bool IsFocusable(int32_t *aTabIndex = nullptr, michael@0: bool aWithMouse = false) MOZ_OVERRIDE; michael@0: michael@0: // check attributes and optionally CSS to see if we should display anything michael@0: bool IsHidden(bool aCheckVisibilityStyle = true) const; michael@0: michael@0: bool IsOpaque() const; michael@0: bool IsTransparentMode() const; michael@0: bool IsPaintedByGecko() const; michael@0: michael@0: nsIntPoint GetWindowOriginInPixels(bool aWindowless); michael@0: michael@0: static void PaintPrintPlugin(nsIFrame* aFrame, michael@0: nsRenderingContext* aRenderingContext, michael@0: const nsRect& aDirtyRect, nsPoint aPt); michael@0: void PrintPlugin(nsRenderingContext& aRenderingContext, michael@0: const nsRect& aDirtyRect); michael@0: void PaintPlugin(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext& aRenderingContext, michael@0: const nsRect& aDirtyRect, const nsRect& aPluginRect); michael@0: michael@0: void NotifyPluginReflowObservers(); michael@0: michael@0: friend class nsPluginInstanceOwner; michael@0: friend class nsDisplayPlugin; michael@0: friend class PluginBackgroundSink; michael@0: michael@0: private: michael@0: // Registers the plugin for a geometry update, and requests a geometry michael@0: // update. This caches the root pres context in michael@0: // mRootPresContextRegisteredWith, so that we can be sure we unregister michael@0: // from the right root prest context in UnregisterPluginForGeometryUpdates. michael@0: void RegisterPluginForGeometryUpdates(); michael@0: michael@0: // Unregisters the plugin for geometry updated with the root pres context michael@0: // stored in mRootPresContextRegisteredWith. michael@0: void UnregisterPluginForGeometryUpdates(); michael@0: michael@0: class PluginEventNotifier : public nsRunnable { michael@0: public: michael@0: PluginEventNotifier(const nsString &aEventType) : michael@0: mEventType(aEventType) {} michael@0: michael@0: NS_IMETHOD Run() MOZ_OVERRIDE; michael@0: private: michael@0: nsString mEventType; michael@0: }; michael@0: michael@0: nsPluginInstanceOwner* mInstanceOwner; // WEAK michael@0: nsView* mInnerView; michael@0: nsCOMPtr mWidget; michael@0: nsIntRect mWindowlessRect; michael@0: /** michael@0: * This is owned by the ReadbackLayer for this nsObjectFrame. It is michael@0: * automatically cleared if the PluginBackgroundSink is destroyed. michael@0: */ michael@0: PluginBackgroundSink* mBackgroundSink; michael@0: michael@0: /** michael@0: * Bounds that we should set the plugin's widget to in the next composite, michael@0: * for plugins with widgets. For plugins without widgets, bounds in device michael@0: * pixels relative to the nearest frame that's a display list reference frame. michael@0: */ michael@0: nsIntRect mNextConfigurationBounds; michael@0: /** michael@0: * Clip region that we should set the plugin's widget to michael@0: * in the next composite. Only meaningful for plugins with widgets. michael@0: */ michael@0: nsTArray mNextConfigurationClipRegion; michael@0: michael@0: bool mReflowCallbackPosted; michael@0: michael@0: // We keep this reference to ensure we can always unregister the michael@0: // plugins we register on the root PresContext. michael@0: // This is only non-null while we have a plugin registered for geometry michael@0: // updates. michael@0: nsRefPtr mRootPresContextRegisteredWith; michael@0: }; michael@0: michael@0: class nsDisplayPlugin : public nsDisplayItem { michael@0: public: michael@0: nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) michael@0: : nsDisplayItem(aBuilder, aFrame) michael@0: { michael@0: MOZ_COUNT_CTOR(nsDisplayPlugin); michael@0: aBuilder->SetContainsPluginItem(); michael@0: } michael@0: #ifdef NS_BUILD_REFCNT_LOGGING michael@0: virtual ~nsDisplayPlugin() { michael@0: MOZ_COUNT_DTOR(nsDisplayPlugin); michael@0: } michael@0: #endif michael@0: michael@0: virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; michael@0: virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, michael@0: bool* aSnap) MOZ_OVERRIDE; michael@0: virtual void Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) MOZ_OVERRIDE; michael@0: virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, michael@0: nsRegion* aVisibleRegion, michael@0: const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; michael@0: michael@0: NS_DISPLAY_DECL_NAME("Plugin", TYPE_PLUGIN) michael@0: michael@0: virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, michael@0: LayerManager* aManager, michael@0: const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE michael@0: { michael@0: return static_cast(mFrame)->BuildLayer(aBuilder, michael@0: aManager, michael@0: this, michael@0: aContainerParameters); michael@0: } michael@0: michael@0: virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, michael@0: LayerManager* aManager, michael@0: const ContainerLayerParameters& aParameters) MOZ_OVERRIDE michael@0: { michael@0: return static_cast(mFrame)->GetLayerState(aBuilder, michael@0: aManager); michael@0: } michael@0: }; michael@0: michael@0: #endif /* nsObjectFrame_h___ */