/src/mozilla-central/layout/generic/nsPluginFrame.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
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/. */ |
6 | | |
7 | | /* rendering objects for replaced elements implemented by a plugin */ |
8 | | |
9 | | #ifndef nsPluginFrame_h___ |
10 | | #define nsPluginFrame_h___ |
11 | | |
12 | | #include "mozilla/Attributes.h" |
13 | | #include "mozilla/EventForwards.h" |
14 | | #include "mozilla/UniquePtr.h" |
15 | | #include "nsIObjectFrame.h" |
16 | | #include "nsFrame.h" |
17 | | #include "nsRegion.h" |
18 | | #include "nsDisplayList.h" |
19 | | #include "nsIReflowCallback.h" |
20 | | #include "Units.h" |
21 | | #include "mozilla/layers/StackingContextHelper.h" |
22 | | #include "mozilla/webrender/WebRenderAPI.h" |
23 | | |
24 | | #ifdef XP_WIN |
25 | | #include <windows.h> // For HWND :( |
26 | | // Undo the windows.h damage |
27 | | #undef GetMessage |
28 | | #undef CreateEvent |
29 | | #undef GetClassName |
30 | | #undef GetBinaryType |
31 | | #undef RemoveDirectory |
32 | | #undef LoadIcon |
33 | | #undef LoadImage |
34 | | #undef GetObject |
35 | | #endif |
36 | | |
37 | | class nsPresContext; |
38 | | class nsRootPresContext; |
39 | | class nsDisplayPlugin; |
40 | | class PluginBackgroundSink; |
41 | | class nsPluginInstanceOwner; |
42 | | |
43 | | namespace mozilla { |
44 | | namespace layers { |
45 | | class ImageContainer; |
46 | | class Layer; |
47 | | class LayerManager; |
48 | | } // namespace layers |
49 | | } // namespace mozilla |
50 | | |
51 | | class PluginFrameDidCompositeObserver; |
52 | | |
53 | | class nsPluginFrame final |
54 | | : public nsFrame |
55 | | , public nsIObjectFrame |
56 | | , public nsIReflowCallback |
57 | | { |
58 | | public: |
59 | | typedef mozilla::LayerState LayerState; |
60 | | typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint; |
61 | | typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect; |
62 | | typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion; |
63 | | typedef mozilla::layers::Layer Layer; |
64 | | typedef mozilla::layers::LayerManager LayerManager; |
65 | | typedef mozilla::layers::ImageContainer ImageContainer; |
66 | | typedef mozilla::layers::StackingContextHelper StackingContextHelper; |
67 | | typedef mozilla::layers::WebRenderLayerManager WebRenderLayerManager; |
68 | | typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand; |
69 | | typedef mozilla::ContainerLayerParameters ContainerLayerParameters; |
70 | | |
71 | | NS_DECL_FRAMEARENA_HELPERS(nsPluginFrame) |
72 | | NS_DECL_QUERYFRAME |
73 | | |
74 | | friend nsIFrame* NS_NewObjectFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle); |
75 | | |
76 | | virtual void Init(nsIContent* aContent, |
77 | | nsContainerFrame* aParent, |
78 | | nsIFrame* aPrevInFlow) override; |
79 | | virtual nscoord GetMinISize(gfxContext *aRenderingContext) override; |
80 | | virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override; |
81 | | virtual void Reflow(nsPresContext* aPresContext, |
82 | | ReflowOutput& aDesiredSize, |
83 | | const ReflowInput& aReflowInput, |
84 | | nsReflowStatus& aStatus) override; |
85 | | virtual void DidReflow(nsPresContext* aPresContext, |
86 | | const ReflowInput* aReflowInput) override; |
87 | | virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, |
88 | | const nsDisplayListSet& aLists) override; |
89 | | |
90 | | virtual nsresult HandleEvent(nsPresContext* aPresContext, |
91 | | mozilla::WidgetGUIEvent* aEvent, |
92 | | nsEventStatus* aEventStatus) override; |
93 | | |
94 | | virtual bool IsFrameOfType(uint32_t aFlags) const override |
95 | 0 | { |
96 | 0 | return nsFrame::IsFrameOfType(aFlags & |
97 | 0 | ~(nsIFrame::eReplaced | nsIFrame::eReplacedSizing)); |
98 | 0 | } |
99 | | |
100 | | #ifdef DEBUG_FRAME_DUMP |
101 | | virtual nsresult GetFrameName(nsAString& aResult) const override; |
102 | | #endif |
103 | | |
104 | | virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override; |
105 | | |
106 | | virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override; |
107 | | |
108 | | NS_IMETHOD GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance) override; |
109 | | |
110 | | virtual void SetIsDocumentActive(bool aIsActive) override; |
111 | | |
112 | | virtual nsresult GetCursor(const nsPoint& aPoint, |
113 | | nsIFrame::Cursor& aCursor) override; |
114 | | |
115 | | // APIs used by nsRootPresContext to set up the widget position/size/clip |
116 | | // region. |
117 | | /** |
118 | | * Set the next widget configuration for the plugin to the desired |
119 | | * position of the plugin's widget, on the assumption that it is not visible |
120 | | * (clipped out or covered by opaque content). |
121 | | * This will only be called for plugins which have been registered |
122 | | * with the root pres context for geometry updates. |
123 | | * If there is no widget associated with the plugin, this will have no effect. |
124 | | */ |
125 | | void SetEmptyWidgetConfiguration() |
126 | 0 | { |
127 | 0 | mNextConfigurationBounds = LayoutDeviceIntRect(0,0,0,0); |
128 | 0 | mNextConfigurationClipRegion.Clear(); |
129 | 0 | } |
130 | | /** |
131 | | * Append the desired widget configuration to aConfigurations. |
132 | | */ |
133 | | void GetWidgetConfiguration(nsTArray<nsIWidget::Configuration>* aConfigurations); |
134 | | |
135 | 0 | LayoutDeviceIntRect GetWidgetlessClipRect() { |
136 | 0 | return RegionFromArray(mNextConfigurationClipRegion).GetBounds(); |
137 | 0 | } |
138 | | |
139 | | /** |
140 | | * Called after all widget position/size/clip regions have been changed |
141 | | * (even if there isn't a widget for this plugin). |
142 | | */ |
143 | | void DidSetWidgetGeometry(); |
144 | | |
145 | | // accessibility support |
146 | | #ifdef ACCESSIBILITY |
147 | | virtual mozilla::a11y::AccType AccessibleType() override; |
148 | | #ifdef XP_WIN |
149 | | NS_IMETHOD GetPluginPort(HWND *aPort); |
150 | | #endif |
151 | | #endif |
152 | | |
153 | | //local methods |
154 | | nsresult PrepForDrawing(nsIWidget *aWidget); |
155 | | |
156 | | // for a given aRoot, this walks the frame tree looking for the next outFrame |
157 | | static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext, |
158 | | nsIFrame* aRoot); |
159 | | |
160 | | // nsIReflowCallback |
161 | | virtual bool ReflowFinished() override; |
162 | | virtual void ReflowCallbackCanceled() override; |
163 | | |
164 | | /** |
165 | | * Builds either an ImageLayer or a ReadbackLayer, depending on the type |
166 | | * of aItem (TYPE_PLUGIN or TYPE_PLUGIN_READBACK respectively). |
167 | | */ |
168 | | already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
169 | | LayerManager* aManager, |
170 | | nsDisplayItem* aItem, |
171 | | const ContainerLayerParameters& aContainerParameters); |
172 | | |
173 | | LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
174 | | LayerManager* aManager); |
175 | | |
176 | | /** |
177 | | * Get the rectangle (relative to this frame) which it will paint. Normally |
178 | | * the frame's content-box but may be smaller if the plugin is rendering |
179 | | * asynchronously and has a different-sized image temporarily. |
180 | | */ |
181 | | nsRect GetPaintedRect(const nsDisplayPlugin* aItem) const; |
182 | | |
183 | | /** |
184 | | * If aSupports has a nsPluginFrame, then prepare it for a DocShell swap. |
185 | | * @see nsSubDocumentFrame::BeginSwapDocShells. |
186 | | * There will be a call to EndSwapDocShells after we were moved to the |
187 | | * new view tree. |
188 | | */ |
189 | | static void BeginSwapDocShells(nsISupports* aSupports, void*); |
190 | | /** |
191 | | * If aSupports has a nsPluginFrame, then set it up after a DocShell swap. |
192 | | * @see nsSubDocumentFrame::EndSwapDocShells. |
193 | | */ |
194 | | static void EndSwapDocShells(nsISupports* aSupports, void*); |
195 | | |
196 | 0 | nsIWidget* GetWidget() override { |
197 | 0 | if (!mInnerView) { |
198 | 0 | return nullptr; |
199 | 0 | } |
200 | 0 | return mWidget; |
201 | 0 | } |
202 | | |
203 | | /** |
204 | | * Adjust the plugin's idea of its size, using aSize as its new size. |
205 | | * (aSize must be in twips) |
206 | | */ |
207 | | void FixupWindow(const nsSize& aSize); |
208 | | |
209 | | /* |
210 | | * Sets up the plugin window and calls SetWindow on the plugin. |
211 | | */ |
212 | | nsresult CallSetWindow(bool aCheckIsHidden = true); |
213 | | |
214 | | void SetInstanceOwner(nsPluginInstanceOwner* aOwner); |
215 | | |
216 | | /** |
217 | | * HandleWheelEventAsDefaultAction() handles eWheel event as default action. |
218 | | * This should be called only when WantsToHandleWheelEventAsDefaultAction() |
219 | | * returns true. |
220 | | */ |
221 | | void HandleWheelEventAsDefaultAction(mozilla::WidgetWheelEvent* aEvent); |
222 | | |
223 | | /** |
224 | | * WantsToHandleWheelEventAsDefaultAction() returns true if the plugin |
225 | | * may want to handle wheel events as default action. |
226 | | */ |
227 | | bool WantsToHandleWheelEventAsDefaultAction() const; |
228 | | |
229 | | bool CreateWebRenderCommands(nsDisplayItem* aItem, |
230 | | mozilla::wr::DisplayListBuilder& aBuilder, |
231 | | mozilla::wr::IpcResourceUpdateQueue& aResources, |
232 | | const StackingContextHelper& aSc, |
233 | | mozilla::layers::WebRenderLayerManager* aManager, |
234 | | nsDisplayListBuilder* aDisplayListBuilder); |
235 | | protected: |
236 | | explicit nsPluginFrame(ComputedStyle* aStyle); |
237 | | virtual ~nsPluginFrame(); |
238 | | |
239 | | // NOTE: This frame class does not inherit from |nsLeafFrame|, so |
240 | | // this is not a virtual method implementation. |
241 | | void GetDesiredSize(nsPresContext* aPresContext, |
242 | | const ReflowInput& aReflowInput, |
243 | | ReflowOutput& aDesiredSize); |
244 | | |
245 | | bool IsFocusable(int32_t *aTabIndex = nullptr, |
246 | | bool aWithMouse = false) override; |
247 | | |
248 | | // check attributes and optionally CSS to see if we should display anything |
249 | | bool IsHidden(bool aCheckVisibilityStyle = true) const; |
250 | | |
251 | | bool IsOpaque() const; |
252 | | bool IsTransparentMode() const; |
253 | | bool IsPaintedByGecko() const; |
254 | | |
255 | | nsIntPoint GetWindowOriginInPixels(bool aWindowless); |
256 | | |
257 | | /* |
258 | | * If this frame is in a remote tab, return the tab offset to |
259 | | * the origin of the chrome window. In non-e10s, this return 0,0. |
260 | | * This api sends a sync ipc request so be careful about use. |
261 | | */ |
262 | | LayoutDeviceIntPoint GetRemoteTabChromeOffset(); |
263 | | |
264 | | static void PaintPrintPlugin(nsIFrame* aFrame, |
265 | | gfxContext* aRenderingContext, |
266 | | const nsRect& aDirtyRect, nsPoint aPt); |
267 | | void PrintPlugin(gfxContext& aRenderingContext, |
268 | | const nsRect& aDirtyRect); |
269 | | void PaintPlugin(nsDisplayListBuilder* aBuilder, |
270 | | gfxContext& aRenderingContext, |
271 | | const nsRect& aDirtyRect, const nsRect& aPluginRect); |
272 | | |
273 | | void NotifyPluginReflowObservers(); |
274 | | |
275 | | friend class nsPluginInstanceOwner; |
276 | | friend class nsDisplayPlugin; |
277 | | friend class PluginBackgroundSink; |
278 | | |
279 | 0 | nsView* GetViewInternal() const override { return mOuterView; } |
280 | 0 | void SetViewInternal(nsView* aView) override { mOuterView = aView; } |
281 | | bool GetBounds(nsDisplayItem* aItem, mozilla::gfx::IntSize& aSize, gfxRect& aRect); |
282 | | |
283 | | private: |
284 | | // Registers the plugin for a geometry update, and requests a geometry |
285 | | // update. This caches the root pres context in |
286 | | // mRootPresContextRegisteredWith, so that we can be sure we unregister |
287 | | // from the right root prest context in UnregisterPluginForGeometryUpdates. |
288 | | void RegisterPluginForGeometryUpdates(); |
289 | | |
290 | | // Unregisters the plugin for geometry updated with the root pres context |
291 | | // stored in mRootPresContextRegisteredWith. |
292 | | void UnregisterPluginForGeometryUpdates(); |
293 | | |
294 | | static const LayoutDeviceIntRegion |
295 | | RegionFromArray(const nsTArray<LayoutDeviceIntRect>& aRects) |
296 | 0 | { |
297 | 0 | LayoutDeviceIntRegion region; |
298 | 0 | for (uint32_t i = 0; i < aRects.Length(); ++i) { |
299 | 0 | region.Or(region, aRects[i]); |
300 | 0 | } |
301 | 0 | return region; |
302 | 0 | } |
303 | | |
304 | | class PluginEventNotifier : public mozilla::Runnable { |
305 | | public: |
306 | | explicit PluginEventNotifier(const nsString& aEventType) |
307 | | : mozilla::Runnable("nsPluginFrame::PluginEventNotifier") |
308 | | , mEventType(aEventType) |
309 | 0 | { |
310 | 0 | } |
311 | | |
312 | | NS_IMETHOD Run() override; |
313 | | private: |
314 | | nsString mEventType; |
315 | | }; |
316 | | |
317 | | nsPluginInstanceOwner* mInstanceOwner; // WEAK |
318 | | nsView* mOuterView; |
319 | | nsView* mInnerView; |
320 | | nsCOMPtr<nsIWidget> mWidget; |
321 | | nsIntRect mWindowlessRect; |
322 | | /** |
323 | | * This is owned by the ReadbackLayer for this nsPluginFrame. It is |
324 | | * automatically cleared if the PluginBackgroundSink is destroyed. |
325 | | */ |
326 | | PluginBackgroundSink* mBackgroundSink; |
327 | | |
328 | | /** |
329 | | * Bounds that we should set the plugin's widget to in the next composite, |
330 | | * for plugins with widgets. For plugins without widgets, bounds in device |
331 | | * pixels relative to the nearest frame that's a display list reference frame. |
332 | | */ |
333 | | LayoutDeviceIntRect mNextConfigurationBounds; |
334 | | /** |
335 | | * Clip region that we should set the plugin's widget to |
336 | | * in the next composite. Only meaningful for plugins with widgets. |
337 | | */ |
338 | | nsTArray<LayoutDeviceIntRect> mNextConfigurationClipRegion; |
339 | | |
340 | | bool mReflowCallbackPosted; |
341 | | |
342 | | // We keep this reference to ensure we can always unregister the |
343 | | // plugins we register on the root PresContext. |
344 | | // This is only non-null while we have a plugin registered for geometry |
345 | | // updates. |
346 | | RefPtr<nsRootPresContext> mRootPresContextRegisteredWith; |
347 | | |
348 | | mozilla::UniquePtr<PluginFrameDidCompositeObserver> mDidCompositeObserver; |
349 | | }; |
350 | | |
351 | | class nsDisplayPluginGeometry : public nsDisplayItemGenericGeometry |
352 | | { |
353 | | public: |
354 | | nsDisplayPluginGeometry(nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder) |
355 | | : nsDisplayItemGenericGeometry(aItem, aBuilder) |
356 | 0 | {} |
357 | | |
358 | | // Plugins MozPaintWait event depends on sync decode, so we always want |
359 | | // to rebuild the display list when sync decoding. |
360 | | virtual bool InvalidateForSyncDecodeImages() const override |
361 | 0 | { |
362 | 0 | return true; |
363 | 0 | } |
364 | | }; |
365 | | |
366 | | class nsDisplayPlugin final : public nsDisplayItem |
367 | | { |
368 | | public: |
369 | | nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
370 | | : nsDisplayItem(aBuilder, aFrame) |
371 | 0 | { |
372 | 0 | MOZ_COUNT_CTOR(nsDisplayPlugin); |
373 | 0 | aBuilder->SetContainsPluginItem(); |
374 | 0 | } |
375 | | #ifdef NS_BUILD_REFCNT_LOGGING |
376 | | virtual ~nsDisplayPlugin() { |
377 | | MOZ_COUNT_DTOR(nsDisplayPlugin); |
378 | | } |
379 | | #endif |
380 | | |
381 | | virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, |
382 | | bool* aSnap) const override; |
383 | | virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
384 | | bool* aSnap) const override; |
385 | | virtual void Paint(nsDisplayListBuilder* aBuilder, |
386 | | gfxContext* aCtx) override; |
387 | | virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
388 | | nsRegion* aVisibleRegion) override; |
389 | | |
390 | | NS_DISPLAY_DECL_NAME("Plugin", TYPE_PLUGIN) |
391 | | |
392 | | virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
393 | | LayerManager* aManager, |
394 | | const ContainerLayerParameters& aContainerParameters) override |
395 | 0 | { |
396 | 0 | return static_cast<nsPluginFrame*>(mFrame)->BuildLayer(aBuilder, |
397 | 0 | aManager, |
398 | 0 | this, |
399 | 0 | aContainerParameters); |
400 | 0 | } |
401 | | |
402 | | virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
403 | | LayerManager* aManager, |
404 | | const ContainerLayerParameters& aParameters) override |
405 | 0 | { |
406 | 0 | return static_cast<nsPluginFrame*>(mFrame)->GetLayerState(aBuilder, |
407 | 0 | aManager); |
408 | 0 | } |
409 | | |
410 | | virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override |
411 | 0 | { |
412 | 0 | return new nsDisplayPluginGeometry(this, aBuilder); |
413 | 0 | } |
414 | | |
415 | | virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder, |
416 | | mozilla::wr::IpcResourceUpdateQueue& aResources, |
417 | | const StackingContextHelper& aSc, |
418 | | mozilla::layers::WebRenderLayerManager* aManager, |
419 | | nsDisplayListBuilder* aDisplayListBuilder) override; |
420 | | }; |
421 | | |
422 | | #endif /* nsPluginFrame_h___ */ |