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