Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 /* rendering objects for replaced elements implemented by a plugin */
8 #ifndef nsObjectFrame_h___
9 #define nsObjectFrame_h___
11 #include "mozilla/Attributes.h"
12 #include "nsIObjectFrame.h"
13 #include "nsFrame.h"
14 #include "nsRegion.h"
15 #include "nsDisplayList.h"
16 #include "nsIReflowCallback.h"
18 #ifdef XP_WIN
19 #include <windows.h> // For HWND :(
20 #endif
22 class nsPresContext;
23 class nsRootPresContext;
24 class nsDisplayPlugin;
25 class nsIOSurface;
26 class PluginBackgroundSink;
27 class nsPluginInstanceOwner;
29 namespace mozilla {
30 namespace layers {
31 class ImageContainer;
32 class Layer;
33 class LayerManager;
34 }
35 }
37 typedef nsFrame nsObjectFrameSuper;
39 class nsObjectFrame : public nsObjectFrameSuper,
40 public nsIObjectFrame,
41 public nsIReflowCallback {
42 public:
43 typedef mozilla::LayerState LayerState;
44 typedef mozilla::layers::Layer Layer;
45 typedef mozilla::layers::LayerManager LayerManager;
46 typedef mozilla::layers::ImageContainer ImageContainer;
47 typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
49 NS_DECL_FRAMEARENA_HELPERS
51 friend nsIFrame* NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
53 NS_DECL_QUERYFRAME
54 NS_DECL_QUERYFRAME_TARGET(nsObjectFrame)
56 virtual void Init(nsIContent* aContent,
57 nsIFrame* aParent,
58 nsIFrame* aPrevInFlow) MOZ_OVERRIDE;
59 virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
60 virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
61 virtual nsresult Reflow(nsPresContext* aPresContext,
62 nsHTMLReflowMetrics& aDesiredSize,
63 const nsHTMLReflowState& aReflowState,
64 nsReflowStatus& aStatus) MOZ_OVERRIDE;
65 virtual nsresult DidReflow(nsPresContext* aPresContext,
66 const nsHTMLReflowState* aReflowState,
67 nsDidReflowStatus aStatus) MOZ_OVERRIDE;
68 virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
69 const nsRect& aDirtyRect,
70 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
72 virtual nsresult HandleEvent(nsPresContext* aPresContext,
73 mozilla::WidgetGUIEvent* aEvent,
74 nsEventStatus* aEventStatus) MOZ_OVERRIDE;
76 virtual nsIAtom* GetType() const MOZ_OVERRIDE;
78 virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
79 {
80 return nsObjectFrameSuper::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced));
81 }
83 virtual bool NeedsView() MOZ_OVERRIDE { return true; }
85 #ifdef DEBUG_FRAME_DUMP
86 virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
87 #endif
89 virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
91 virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
93 NS_METHOD GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance) MOZ_OVERRIDE;
95 virtual void SetIsDocumentActive(bool aIsActive) MOZ_OVERRIDE;
97 virtual nsresult GetCursor(const nsPoint& aPoint,
98 nsIFrame::Cursor& aCursor) MOZ_OVERRIDE;
100 // APIs used by nsRootPresContext to set up the widget position/size/clip
101 // region.
102 /**
103 * Set the next widget configuration for the plugin to the desired
104 * position of the plugin's widget, on the assumption that it is not visible
105 * (clipped out or covered by opaque content).
106 * This will only be called for plugins which have been registered
107 * with the root pres context for geometry updates.
108 * If there is no widget associated with the plugin, this will have no effect.
109 */
110 void SetEmptyWidgetConfiguration()
111 {
112 mNextConfigurationBounds = nsIntRect(0,0,0,0);
113 mNextConfigurationClipRegion.Clear();
114 }
115 /**
116 * Append the desired widget configuration to aConfigurations.
117 */
118 void GetWidgetConfiguration(nsTArray<nsIWidget::Configuration>* aConfigurations)
119 {
120 if (mWidget) {
121 if (!mWidget->GetParent()) {
122 // Plugin widgets should not be toplevel except when they're out of the
123 // document, in which case the plugin should not be registered for
124 // geometry updates and this should not be called. But apparently we
125 // have bugs where mWidget sometimes is toplevel here. Bail out.
126 NS_ERROR("Plugin widgets registered for geometry updates should not be toplevel");
127 return;
128 }
129 nsIWidget::Configuration* configuration = aConfigurations->AppendElement();
130 configuration->mChild = mWidget;
131 configuration->mBounds = mNextConfigurationBounds;
132 configuration->mClipRegion = mNextConfigurationClipRegion;
133 }
134 }
135 /**
136 * Called after all widget position/size/clip regions have been changed
137 * (even if there isn't a widget for this plugin).
138 */
139 void DidSetWidgetGeometry();
141 // accessibility support
142 #ifdef ACCESSIBILITY
143 virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
144 #ifdef XP_WIN
145 NS_IMETHOD GetPluginPort(HWND *aPort);
146 #endif
147 #endif
149 //local methods
150 nsresult PrepForDrawing(nsIWidget *aWidget);
152 // for a given aRoot, this walks the frame tree looking for the next outFrame
153 static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext,
154 nsIFrame* aRoot);
156 // nsIReflowCallback
157 virtual bool ReflowFinished() MOZ_OVERRIDE;
158 virtual void ReflowCallbackCanceled() MOZ_OVERRIDE;
160 /**
161 * Builds either an ImageLayer or a ReadbackLayer, depending on the type
162 * of aItem (TYPE_PLUGIN or TYPE_PLUGIN_READBACK respectively).
163 */
164 already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
165 LayerManager* aManager,
166 nsDisplayItem* aItem,
167 const ContainerLayerParameters& aContainerParameters);
169 LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
170 LayerManager* aManager);
172 /**
173 * Get the rectangle (relative to this frame) which it will paint. Normally
174 * the frame's content-box but may be smaller if the plugin is rendering
175 * asynchronously and has a different-sized image temporarily.
176 */
177 nsRect GetPaintedRect(nsDisplayPlugin* aItem);
179 /**
180 * If aContent has a nsObjectFrame, then prepare it for a DocShell swap.
181 * @see nsSubDocumentFrame::BeginSwapDocShells.
182 * There will be a call to EndSwapDocShells after we were moved to the
183 * new view tree.
184 */
185 static void BeginSwapDocShells(nsIContent* aContent, void*);
186 /**
187 * If aContent has a nsObjectFrame, then set it up after a DocShell swap.
188 * @see nsSubDocumentFrame::EndSwapDocShells.
189 */
190 static void EndSwapDocShells(nsIContent* aContent, void*);
192 nsIWidget* GetWidget() MOZ_OVERRIDE { return mInnerView ? mWidget : nullptr; }
194 /**
195 * Adjust the plugin's idea of its size, using aSize as its new size.
196 * (aSize must be in twips)
197 */
198 void FixupWindow(const nsSize& aSize);
200 /*
201 * Sets up the plugin window and calls SetWindow on the plugin.
202 */
203 nsresult CallSetWindow(bool aCheckIsHidden = true);
205 void SetInstanceOwner(nsPluginInstanceOwner* aOwner);
207 protected:
208 nsObjectFrame(nsStyleContext* aContext);
209 virtual ~nsObjectFrame();
211 // NOTE: This frame class does not inherit from |nsLeafFrame|, so
212 // this is not a virtual method implementation.
213 void GetDesiredSize(nsPresContext* aPresContext,
214 const nsHTMLReflowState& aReflowState,
215 nsHTMLReflowMetrics& aDesiredSize);
217 bool IsFocusable(int32_t *aTabIndex = nullptr,
218 bool aWithMouse = false) MOZ_OVERRIDE;
220 // check attributes and optionally CSS to see if we should display anything
221 bool IsHidden(bool aCheckVisibilityStyle = true) const;
223 bool IsOpaque() const;
224 bool IsTransparentMode() const;
225 bool IsPaintedByGecko() const;
227 nsIntPoint GetWindowOriginInPixels(bool aWindowless);
229 static void PaintPrintPlugin(nsIFrame* aFrame,
230 nsRenderingContext* aRenderingContext,
231 const nsRect& aDirtyRect, nsPoint aPt);
232 void PrintPlugin(nsRenderingContext& aRenderingContext,
233 const nsRect& aDirtyRect);
234 void PaintPlugin(nsDisplayListBuilder* aBuilder,
235 nsRenderingContext& aRenderingContext,
236 const nsRect& aDirtyRect, const nsRect& aPluginRect);
238 void NotifyPluginReflowObservers();
240 friend class nsPluginInstanceOwner;
241 friend class nsDisplayPlugin;
242 friend class PluginBackgroundSink;
244 private:
245 // Registers the plugin for a geometry update, and requests a geometry
246 // update. This caches the root pres context in
247 // mRootPresContextRegisteredWith, so that we can be sure we unregister
248 // from the right root prest context in UnregisterPluginForGeometryUpdates.
249 void RegisterPluginForGeometryUpdates();
251 // Unregisters the plugin for geometry updated with the root pres context
252 // stored in mRootPresContextRegisteredWith.
253 void UnregisterPluginForGeometryUpdates();
255 class PluginEventNotifier : public nsRunnable {
256 public:
257 PluginEventNotifier(const nsString &aEventType) :
258 mEventType(aEventType) {}
260 NS_IMETHOD Run() MOZ_OVERRIDE;
261 private:
262 nsString mEventType;
263 };
265 nsPluginInstanceOwner* mInstanceOwner; // WEAK
266 nsView* mInnerView;
267 nsCOMPtr<nsIWidget> mWidget;
268 nsIntRect mWindowlessRect;
269 /**
270 * This is owned by the ReadbackLayer for this nsObjectFrame. It is
271 * automatically cleared if the PluginBackgroundSink is destroyed.
272 */
273 PluginBackgroundSink* mBackgroundSink;
275 /**
276 * Bounds that we should set the plugin's widget to in the next composite,
277 * for plugins with widgets. For plugins without widgets, bounds in device
278 * pixels relative to the nearest frame that's a display list reference frame.
279 */
280 nsIntRect mNextConfigurationBounds;
281 /**
282 * Clip region that we should set the plugin's widget to
283 * in the next composite. Only meaningful for plugins with widgets.
284 */
285 nsTArray<nsIntRect> mNextConfigurationClipRegion;
287 bool mReflowCallbackPosted;
289 // We keep this reference to ensure we can always unregister the
290 // plugins we register on the root PresContext.
291 // This is only non-null while we have a plugin registered for geometry
292 // updates.
293 nsRefPtr<nsRootPresContext> mRootPresContextRegisteredWith;
294 };
296 class nsDisplayPlugin : public nsDisplayItem {
297 public:
298 nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
299 : nsDisplayItem(aBuilder, aFrame)
300 {
301 MOZ_COUNT_CTOR(nsDisplayPlugin);
302 aBuilder->SetContainsPluginItem();
303 }
304 #ifdef NS_BUILD_REFCNT_LOGGING
305 virtual ~nsDisplayPlugin() {
306 MOZ_COUNT_DTOR(nsDisplayPlugin);
307 }
308 #endif
310 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;
311 virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
312 bool* aSnap) MOZ_OVERRIDE;
313 virtual void Paint(nsDisplayListBuilder* aBuilder,
314 nsRenderingContext* aCtx) MOZ_OVERRIDE;
315 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
316 nsRegion* aVisibleRegion,
317 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
319 NS_DISPLAY_DECL_NAME("Plugin", TYPE_PLUGIN)
321 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
322 LayerManager* aManager,
323 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
324 {
325 return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder,
326 aManager,
327 this,
328 aContainerParameters);
329 }
331 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
332 LayerManager* aManager,
333 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE
334 {
335 return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder,
336 aManager);
337 }
338 };
340 #endif /* nsObjectFrame_h___ */