diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /layout/generic/nsPluginFrame.h | |
parent | Initial commit. (diff) | |
download | firefox-upstream.tar.xz firefox-upstream.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'layout/generic/nsPluginFrame.h')
-rw-r--r-- | layout/generic/nsPluginFrame.h | 399 |
1 files changed, 399 insertions, 0 deletions
diff --git a/layout/generic/nsPluginFrame.h b/layout/generic/nsPluginFrame.h new file mode 100644 index 0000000000..7a1509c876 --- /dev/null +++ b/layout/generic/nsPluginFrame.h @@ -0,0 +1,399 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* rendering objects for replaced elements implemented by a plugin */ + +#ifndef nsPluginFrame_h___ +#define nsPluginFrame_h___ + +#include "mozilla/Attributes.h" +#include "mozilla/EventForwards.h" +#include "mozilla/UniquePtr.h" +#include "nsIObjectFrame.h" +#include "nsIFrame.h" +#include "nsRegion.h" +#include "nsDisplayList.h" +#include "nsIReflowCallback.h" +#include "Units.h" +#include "mozilla/layers/StackingContextHelper.h" +#include "mozilla/webrender/WebRenderAPI.h" + +#ifdef XP_WIN +# include <windows.h> // For HWND :( +// Undo the windows.h damage +# undef GetMessage +# undef CreateEvent +# undef GetClassName +# undef GetBinaryType +# undef RemoveDirectory +# undef LoadIcon +# undef LoadImage +# undef GetObject +#endif + +class nsPresContext; +class nsRootPresContext; +class nsDisplayPlugin; +class PluginBackgroundSink; +class nsPluginInstanceOwner; + +namespace mozilla { +class PresShell; +namespace layers { +class ImageContainer; +class Layer; +class LayerManager; +} // namespace layers +} // namespace mozilla + +class PluginFrameDidCompositeObserver; + +class nsPluginFrame final : public nsIFrame, + public nsIObjectFrame, + public nsIReflowCallback { + public: + typedef mozilla::LayerState LayerState; + typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint; + typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect; + typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion; + typedef mozilla::layers::Layer Layer; + typedef mozilla::layers::LayerManager LayerManager; + typedef mozilla::layers::ImageContainer ImageContainer; + typedef mozilla::layers::StackingContextHelper StackingContextHelper; + typedef mozilla::layers::RenderRootStateManager RenderRootStateManager; + typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand; + typedef mozilla::ContainerLayerParameters ContainerLayerParameters; + + NS_DECL_FRAMEARENA_HELPERS(nsPluginFrame) + NS_DECL_QUERYFRAME + + friend nsIFrame* NS_NewObjectFrame(mozilla::PresShell* aPresShell, + ComputedStyle* aStyle); + + virtual void Init(nsIContent* aContent, nsContainerFrame* aParent, + nsIFrame* aPrevInFlow) override; + virtual nscoord GetMinISize(gfxContext* aRenderingContext) override; + virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override; + virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, + const ReflowInput& aReflowInput, + nsReflowStatus& aStatus) override; + virtual void DidReflow(nsPresContext* aPresContext, + const ReflowInput* aReflowInput) override; + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsDisplayListSet& aLists) override; + + MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual nsresult HandleEvent( + nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent, + nsEventStatus* aEventStatus) override; + + virtual bool IsFrameOfType(uint32_t aFlags) const override { + return nsIFrame::IsFrameOfType( + aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing)); + } + +#ifdef DEBUG_FRAME_DUMP + virtual nsresult GetFrameName(nsAString& aResult) const override; +#endif + + virtual void DestroyFrom(nsIFrame* aDestructRoot, + PostDestroyData& aPostDestroyData) override; + + virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override; + + nsNPAPIPluginInstance* GetPluginInstance() override; + + virtual void SetIsDocumentActive(bool aIsActive) override; + + mozilla::Maybe<Cursor> GetCursor(const nsPoint&) override; + + // APIs used by nsRootPresContext to set up the widget position/size/clip + // region. + /** + * Set the next widget configuration for the plugin to the desired + * position of the plugin's widget, on the assumption that it is not visible + * (clipped out or covered by opaque content). + * This will only be called for plugins which have been registered + * with the root pres context for geometry updates. + * If there is no widget associated with the plugin, this will have no effect. + */ + void SetEmptyWidgetConfiguration() { + mNextConfigurationBounds = LayoutDeviceIntRect(0, 0, 0, 0); + mNextConfigurationClipRegion.Clear(); + } + /** + * Append the desired widget configuration to aConfigurations. + */ + void GetWidgetConfiguration( + nsTArray<nsIWidget::Configuration>* aConfigurations); + + LayoutDeviceIntRect GetWidgetlessClipRect() { + return RegionFromArray(mNextConfigurationClipRegion).GetBounds(); + } + + /** + * Called after all widget position/size/clip regions have been changed + * (even if there isn't a widget for this plugin). + */ + void DidSetWidgetGeometry(); + + // accessibility support +#ifdef ACCESSIBILITY + virtual mozilla::a11y::AccType AccessibleType() override; +# ifdef XP_WIN + NS_IMETHOD GetPluginPort(HWND* aPort); +# endif +#endif + + // local methods + nsresult PrepForDrawing(nsIWidget* aWidget); + + // for a given aRoot, this walks the frame tree looking for the next outFrame + static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext, + nsIFrame* aRoot); + + // nsIReflowCallback + virtual bool ReflowFinished() override; + virtual void ReflowCallbackCanceled() override; + + /** + * Builds either an ImageLayer or a ReadbackLayer, depending on the type + * of aItem (TYPE_PLUGIN or TYPE_PLUGIN_READBACK respectively). + */ + already_AddRefed<Layer> BuildLayer( + nsDisplayListBuilder* aBuilder, LayerManager* aManager, + nsDisplayItem* aItem, + const ContainerLayerParameters& aContainerParameters); + + LayerState GetLayerState(nsDisplayListBuilder* aBuilder, + LayerManager* aManager); + + /** + * Get the rectangle (relative to this frame) which it will paint. Normally + * the frame's content-box but may be smaller if the plugin is rendering + * asynchronously and has a different-sized image temporarily. + */ + nsRect GetPaintedRect(const nsDisplayPlugin* aItem) const; + + /** + * If aSupports has a nsPluginFrame, then prepare it for a DocShell swap. + * @see nsSubDocumentFrame::BeginSwapDocShells. + * There will be a call to EndSwapDocShells after we were moved to the + * new view tree. + */ + static void BeginSwapDocShells(nsISupports* aSupports); + /** + * If aSupports has a nsPluginFrame, then set it up after a DocShell swap. + * @see nsSubDocumentFrame::EndSwapDocShells. + */ + static void EndSwapDocShells(nsISupports* aSupports); + + nsIWidget* GetWidget() override { + if (!mInnerView) { + return nullptr; + } + return mWidget; + } + + /** + * Adjust the plugin's idea of its size, using aSize as its new size. + * (aSize must be in twips) + */ + void FixupWindow(const nsSize& aSize); + + /* + * Sets up the plugin window and calls SetWindow on the plugin. + */ + nsresult CallSetWindow(bool aCheckIsHidden = true); + + void SetInstanceOwner(nsPluginInstanceOwner* aOwner); + + /** + * HandleWheelEventAsDefaultAction() handles eWheel event as default action. + * This should be called only when WantsToHandleWheelEventAsDefaultAction() + * returns true. + */ + void HandleWheelEventAsDefaultAction(mozilla::WidgetWheelEvent* aEvent); + + /** + * WantsToHandleWheelEventAsDefaultAction() returns true if the plugin + * may want to handle wheel events as default action. + */ + bool WantsToHandleWheelEventAsDefaultAction() const; + + bool CreateWebRenderCommands( + nsDisplayItem* aItem, mozilla::wr::DisplayListBuilder& aBuilder, + mozilla::wr::IpcResourceUpdateQueue& aResources, + const StackingContextHelper& aSc, + mozilla::layers::RenderRootStateManager* aManager, + nsDisplayListBuilder* aDisplayListBuilder); + + protected: + explicit nsPluginFrame(ComputedStyle* aStyle, nsPresContext* aPresContext); + virtual ~nsPluginFrame(); + + // NOTE: This frame class does not inherit from |nsLeafFrame|, so + // this is not a virtual method implementation. + void GetDesiredSize(nsPresContext* aPresContext, + const ReflowInput& aReflowInput, + ReflowOutput& aDesiredSize); + + // check attributes and optionally CSS to see if we should display anything + bool IsHidden(bool aCheckVisibilityStyle = true) const; + + bool IsOpaque() const; + bool IsTransparentMode() const; + bool IsPaintedByGecko() const; + + nsIntPoint GetWindowOriginInPixels(bool aWindowless); + + /* + * If this frame is in a remote tab, return the tab offset to + * the origin of the chrome window. In non-e10s, this return 0,0. + * This api sends a sync ipc request so be careful about use. + */ + LayoutDeviceIntPoint GetRemoteTabChromeOffset(); + + static void PaintPrintPlugin(nsIFrame* aFrame, gfxContext* aRenderingContext, + const nsRect& aDirtyRect, nsPoint aPt); + void PrintPlugin(gfxContext& aRenderingContext, const nsRect& aDirtyRect); + void PaintPlugin(nsDisplayListBuilder* aBuilder, + gfxContext& aRenderingContext, const nsRect& aDirtyRect, + const nsRect& aPluginRect); + + void NotifyPluginReflowObservers(); + + friend class nsPluginInstanceOwner; + friend class nsDisplayPlugin; + friend class PluginBackgroundSink; + + nsView* GetViewInternal() const override { return mOuterView; } + void SetViewInternal(nsView* aView) override { mOuterView = aView; } + bool GetBounds(nsDisplayItem* aItem, mozilla::gfx::IntSize& aSize, + gfxRect& aRect); + + private: + // Registers the plugin for a geometry update, and requests a geometry + // update. This caches the root pres context in + // mRootPresContextRegisteredWith, so that we can be sure we unregister + // from the right root prest context in UnregisterPluginForGeometryUpdates. + void RegisterPluginForGeometryUpdates(); + + // Unregisters the plugin for geometry updated with the root pres context + // stored in mRootPresContextRegisteredWith. + void UnregisterPluginForGeometryUpdates(); + + static const LayoutDeviceIntRegion RegionFromArray( + const nsTArray<LayoutDeviceIntRect>& aRects) { + LayoutDeviceIntRegion region; + for (uint32_t i = 0; i < aRects.Length(); ++i) { + region.Or(region, aRects[i]); + } + return region; + } + + class PluginEventNotifier : public mozilla::Runnable { + public: + explicit PluginEventNotifier(const nsString& aEventType) + : mozilla::Runnable("nsPluginFrame::PluginEventNotifier"), + mEventType(aEventType) {} + + NS_IMETHOD Run() override; + + private: + nsString mEventType; + }; + + nsPluginInstanceOwner* mInstanceOwner; // WEAK + nsView* mOuterView; + nsView* mInnerView; + nsCOMPtr<nsIWidget> mWidget; + nsIntRect mWindowlessRect; + /** + * This is owned by the ReadbackLayer for this nsPluginFrame. It is + * automatically cleared if the PluginBackgroundSink is destroyed. + */ + PluginBackgroundSink* mBackgroundSink; + + /** + * Bounds that we should set the plugin's widget to in the next composite, + * for plugins with widgets. For plugins without widgets, bounds in device + * pixels relative to the nearest frame that's a display list reference frame. + */ + LayoutDeviceIntRect mNextConfigurationBounds; + /** + * Clip region that we should set the plugin's widget to + * in the next composite. Only meaningful for plugins with widgets. + */ + nsTArray<LayoutDeviceIntRect> mNextConfigurationClipRegion; + + bool mReflowCallbackPosted; + + // We keep this reference to ensure we can always unregister the + // plugins we register on the root PresContext. + // This is only non-null while we have a plugin registered for geometry + // updates. + RefPtr<nsRootPresContext> mRootPresContextRegisteredWith; + + mozilla::UniquePtr<PluginFrameDidCompositeObserver> mDidCompositeObserver; +}; + +class nsDisplayPluginGeometry : public nsDisplayItemGenericGeometry { + public: + nsDisplayPluginGeometry(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder) + : nsDisplayItemGenericGeometry(aItem, aBuilder) {} + + // Plugins MozPaintWait event depends on sync decode, so we always want + // to rebuild the display list when sync decoding. + virtual bool InvalidateForSyncDecodeImages() const override { return true; } +}; + +class nsDisplayPlugin final : public nsPaintedDisplayItem { + public: + nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) + : nsPaintedDisplayItem(aBuilder, aFrame) { + MOZ_COUNT_CTOR(nsDisplayPlugin); + aBuilder->SetContainsPluginItem(); + } + MOZ_COUNTED_DTOR_OVERRIDE(nsDisplayPlugin) + + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) const override; + virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, + bool* aSnap) const override; + virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override; + virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, + nsRegion* aVisibleRegion) override; + + NS_DISPLAY_DECL_NAME("Plugin", TYPE_PLUGIN) + + virtual already_AddRefed<Layer> BuildLayer( + nsDisplayListBuilder* aBuilder, LayerManager* aManager, + const ContainerLayerParameters& aContainerParameters) override { + return static_cast<nsPluginFrame*>(mFrame)->BuildLayer( + aBuilder, aManager, this, aContainerParameters); + } + + virtual LayerState GetLayerState( + nsDisplayListBuilder* aBuilder, LayerManager* aManager, + const ContainerLayerParameters& aParameters) override { + return static_cast<nsPluginFrame*>(mFrame)->GetLayerState(aBuilder, + aManager); + } + + virtual nsDisplayItemGeometry* AllocateGeometry( + nsDisplayListBuilder* aBuilder) override { + return new nsDisplayPluginGeometry(this, aBuilder); + } + + virtual bool CreateWebRenderCommands( + mozilla::wr::DisplayListBuilder& aBuilder, + mozilla::wr::IpcResourceUpdateQueue& aResources, + const StackingContextHelper& aSc, + mozilla::layers::RenderRootStateManager* aManager, + nsDisplayListBuilder* aDisplayListBuilder) override; +}; + +#endif /* nsPluginFrame_h___ */ |