|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 // vim:set ts=2 sts=2 sw=2 et cin: |
|
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 #include "nsObjectFrame.h" |
|
10 |
|
11 #include "gfx2DGlue.h" |
|
12 #include "mozilla/BasicEvents.h" |
|
13 #ifdef XP_WIN |
|
14 // This is needed for DoublePassRenderingEvent. |
|
15 #include "mozilla/plugins/PluginMessageUtils.h" |
|
16 #endif |
|
17 |
|
18 #include "nscore.h" |
|
19 #include "nsCOMPtr.h" |
|
20 #include "nsPresContext.h" |
|
21 #include "nsIPresShell.h" |
|
22 #include "nsWidgetsCID.h" |
|
23 #include "nsView.h" |
|
24 #include "nsViewManager.h" |
|
25 #include "nsString.h" |
|
26 #include "nsGkAtoms.h" |
|
27 #include "nsIPluginInstanceOwner.h" |
|
28 #include "nsNPAPIPluginInstance.h" |
|
29 #include "nsIDOMElement.h" |
|
30 #include "nsRenderingContext.h" |
|
31 #include "npapi.h" |
|
32 #include "nsIObjectLoadingContent.h" |
|
33 #include "nsContentUtils.h" |
|
34 #include "nsDisplayList.h" |
|
35 #include "nsFocusManager.h" |
|
36 #include "nsLayoutUtils.h" |
|
37 #include "nsFrameManager.h" |
|
38 #include "nsIObserverService.h" |
|
39 #include "GeckoProfiler.h" |
|
40 #include <algorithm> |
|
41 |
|
42 #include "nsIObjectFrame.h" |
|
43 #include "nsPluginNativeWindow.h" |
|
44 #include "FrameLayerBuilder.h" |
|
45 |
|
46 #include "ImageLayers.h" |
|
47 #include "nsPluginInstanceOwner.h" |
|
48 |
|
49 #ifdef XP_WIN |
|
50 #include "gfxWindowsNativeDrawing.h" |
|
51 #include "gfxWindowsSurface.h" |
|
52 #endif |
|
53 |
|
54 #include "Layers.h" |
|
55 #include "ReadbackLayer.h" |
|
56 #include "ImageContainer.h" |
|
57 |
|
58 // accessibility support |
|
59 #ifdef ACCESSIBILITY |
|
60 #include "nsAccessibilityService.h" |
|
61 #endif |
|
62 |
|
63 #ifdef MOZ_LOGGING |
|
64 #define FORCE_PR_LOG 1 /* Allow logging in the release build */ |
|
65 #endif /* MOZ_LOGGING */ |
|
66 #include "prlog.h" |
|
67 |
|
68 #ifdef XP_MACOSX |
|
69 #include "gfxQuartzNativeDrawing.h" |
|
70 #include "nsPluginUtilsOSX.h" |
|
71 #include "mozilla/gfx/QuartzSupport.h" |
|
72 #endif |
|
73 |
|
74 #ifdef MOZ_X11 |
|
75 #include "mozilla/X11Util.h" |
|
76 using mozilla::DefaultXDisplay; |
|
77 #endif |
|
78 |
|
79 #ifdef XP_WIN |
|
80 #include <wtypes.h> |
|
81 #include <winuser.h> |
|
82 #endif |
|
83 |
|
84 #ifdef MOZ_WIDGET_ANDROID |
|
85 #include "AndroidBridge.h" |
|
86 #include "GLContext.h" |
|
87 #endif |
|
88 |
|
89 #ifdef CreateEvent // Thank you MS. |
|
90 #undef CreateEvent |
|
91 #endif |
|
92 |
|
93 #ifdef PR_LOGGING |
|
94 static PRLogModuleInfo * |
|
95 GetObjectFrameLog() |
|
96 { |
|
97 static PRLogModuleInfo *sLog; |
|
98 if (!sLog) |
|
99 sLog = PR_NewLogModule("nsObjectFrame"); |
|
100 return sLog; |
|
101 } |
|
102 #endif /* PR_LOGGING */ |
|
103 |
|
104 #if defined(XP_MACOSX) && !defined(__LP64__) |
|
105 |
|
106 // The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7 |
|
107 // and up (though the QuickDraw APIs defined in them are still present) -- so |
|
108 // we need to supply the relevant parts of their contents here. It's likely |
|
109 // that Apple will eventually remove the APIs themselves (probably in OS X |
|
110 // 10.8), so we need to make them weak imports, and test for their presence |
|
111 // before using them. |
|
112 extern "C" { |
|
113 #if !defined(__QUICKDRAWAPI__) |
|
114 extern void SetRect( |
|
115 Rect * r, |
|
116 short left, |
|
117 short top, |
|
118 short right, |
|
119 short bottom) |
|
120 __attribute__((weak_import)); |
|
121 #endif /* __QUICKDRAWAPI__ */ |
|
122 |
|
123 #if !defined(__QDOFFSCREEN__) |
|
124 extern QDErr NewGWorldFromPtr( |
|
125 GWorldPtr * offscreenGWorld, |
|
126 UInt32 PixelFormat, |
|
127 const Rect * boundsRect, |
|
128 CTabHandle cTable, /* can be nullptr */ |
|
129 GDHandle aGDevice, /* can be nullptr */ |
|
130 GWorldFlags flags, |
|
131 Ptr newBuffer, |
|
132 SInt32 rowBytes) |
|
133 __attribute__((weak_import)); |
|
134 extern void DisposeGWorld(GWorldPtr offscreenGWorld) |
|
135 __attribute__((weak_import)); |
|
136 #endif /* __QDOFFSCREEN__ */ |
|
137 } |
|
138 |
|
139 #endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */ |
|
140 |
|
141 using namespace mozilla; |
|
142 using namespace mozilla::gfx; |
|
143 using namespace mozilla::layers; |
|
144 |
|
145 class PluginBackgroundSink : public ReadbackSink { |
|
146 public: |
|
147 PluginBackgroundSink(nsObjectFrame* aFrame, uint64_t aStartSequenceNumber) |
|
148 : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {} |
|
149 ~PluginBackgroundSink() |
|
150 { |
|
151 if (mFrame) { |
|
152 mFrame->mBackgroundSink = nullptr; |
|
153 } |
|
154 } |
|
155 |
|
156 virtual void SetUnknown(uint64_t aSequenceNumber) |
|
157 { |
|
158 if (!AcceptUpdate(aSequenceNumber)) |
|
159 return; |
|
160 mFrame->mInstanceOwner->SetBackgroundUnknown(); |
|
161 } |
|
162 |
|
163 virtual already_AddRefed<gfxContext> |
|
164 BeginUpdate(const nsIntRect& aRect, uint64_t aSequenceNumber) |
|
165 { |
|
166 if (!AcceptUpdate(aSequenceNumber)) |
|
167 return nullptr; |
|
168 return mFrame->mInstanceOwner->BeginUpdateBackground(aRect); |
|
169 } |
|
170 |
|
171 virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect) |
|
172 { |
|
173 return mFrame->mInstanceOwner->EndUpdateBackground(aContext, aRect); |
|
174 } |
|
175 |
|
176 void Destroy() { mFrame = nullptr; } |
|
177 |
|
178 protected: |
|
179 bool AcceptUpdate(uint64_t aSequenceNumber) { |
|
180 if (aSequenceNumber > mLastSequenceNumber && mFrame && |
|
181 mFrame->mInstanceOwner) { |
|
182 mLastSequenceNumber = aSequenceNumber; |
|
183 return true; |
|
184 } |
|
185 return false; |
|
186 } |
|
187 |
|
188 uint64_t mLastSequenceNumber; |
|
189 nsObjectFrame* mFrame; |
|
190 }; |
|
191 |
|
192 nsObjectFrame::nsObjectFrame(nsStyleContext* aContext) |
|
193 : nsObjectFrameSuper(aContext) |
|
194 , mReflowCallbackPosted(false) |
|
195 { |
|
196 PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG, |
|
197 ("Created new nsObjectFrame %p\n", this)); |
|
198 } |
|
199 |
|
200 nsObjectFrame::~nsObjectFrame() |
|
201 { |
|
202 PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG, |
|
203 ("nsObjectFrame %p deleted\n", this)); |
|
204 } |
|
205 |
|
206 NS_QUERYFRAME_HEAD(nsObjectFrame) |
|
207 NS_QUERYFRAME_ENTRY(nsObjectFrame) |
|
208 NS_QUERYFRAME_ENTRY(nsIObjectFrame) |
|
209 NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper) |
|
210 |
|
211 #ifdef ACCESSIBILITY |
|
212 a11y::AccType |
|
213 nsObjectFrame::AccessibleType() |
|
214 { |
|
215 return a11y::ePluginType; |
|
216 } |
|
217 |
|
218 #ifdef XP_WIN |
|
219 NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort) |
|
220 { |
|
221 *aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget(); |
|
222 return NS_OK; |
|
223 } |
|
224 #endif |
|
225 #endif |
|
226 |
|
227 void |
|
228 nsObjectFrame::Init(nsIContent* aContent, |
|
229 nsIFrame* aParent, |
|
230 nsIFrame* aPrevInFlow) |
|
231 { |
|
232 PR_LOG(GetObjectFrameLog(), PR_LOG_DEBUG, |
|
233 ("Initializing nsObjectFrame %p for content %p\n", this, aContent)); |
|
234 |
|
235 nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow); |
|
236 } |
|
237 |
|
238 void |
|
239 nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot) |
|
240 { |
|
241 if (mReflowCallbackPosted) { |
|
242 PresContext()->PresShell()->CancelReflowCallback(this); |
|
243 } |
|
244 |
|
245 // Tell content owner of the instance to disconnect its frame. |
|
246 nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent)); |
|
247 NS_ASSERTION(objContent, "Why not an object loading content?"); |
|
248 |
|
249 // The content might not have a reference to the instance owner any longer in |
|
250 // the case of re-entry during instantiation or teardown, so make sure we're |
|
251 // dissociated. |
|
252 if (mInstanceOwner) { |
|
253 mInstanceOwner->SetFrame(nullptr); |
|
254 } |
|
255 objContent->HasNewFrame(nullptr); |
|
256 |
|
257 if (mBackgroundSink) { |
|
258 mBackgroundSink->Destroy(); |
|
259 } |
|
260 |
|
261 nsObjectFrameSuper::DestroyFrom(aDestructRoot); |
|
262 } |
|
263 |
|
264 /* virtual */ void |
|
265 nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) |
|
266 { |
|
267 if (HasView()) { |
|
268 nsView* view = GetView(); |
|
269 nsViewManager* vm = view->GetViewManager(); |
|
270 if (vm) { |
|
271 nsViewVisibility visibility = |
|
272 IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow; |
|
273 vm->SetViewVisibility(view, visibility); |
|
274 } |
|
275 } |
|
276 |
|
277 nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext); |
|
278 } |
|
279 |
|
280 nsIAtom* |
|
281 nsObjectFrame::GetType() const |
|
282 { |
|
283 return nsGkAtoms::objectFrame; |
|
284 } |
|
285 |
|
286 #ifdef DEBUG_FRAME_DUMP |
|
287 nsresult |
|
288 nsObjectFrame::GetFrameName(nsAString& aResult) const |
|
289 { |
|
290 return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult); |
|
291 } |
|
292 #endif |
|
293 |
|
294 nsresult |
|
295 nsObjectFrame::PrepForDrawing(nsIWidget *aWidget) |
|
296 { |
|
297 mWidget = aWidget; |
|
298 |
|
299 nsView* view = GetView(); |
|
300 NS_ASSERTION(view, "Object frames must have views"); |
|
301 if (!view) { |
|
302 return NS_ERROR_FAILURE; |
|
303 } |
|
304 |
|
305 nsViewManager* viewMan = view->GetViewManager(); |
|
306 // mark the view as hidden since we don't know the (x,y) until Paint |
|
307 // XXX is the above comment correct? |
|
308 viewMan->SetViewVisibility(view, nsViewVisibility_kHide); |
|
309 |
|
310 //this is ugly. it was ripped off from didreflow(). MMP |
|
311 // Position and size view relative to its parent, not relative to our |
|
312 // parent frame (our parent frame may not have a view). |
|
313 |
|
314 nsView* parentWithView; |
|
315 nsPoint origin; |
|
316 nsRect r(0, 0, mRect.width, mRect.height); |
|
317 |
|
318 GetOffsetFromView(origin, &parentWithView); |
|
319 viewMan->ResizeView(view, r); |
|
320 viewMan->MoveViewTo(view, origin.x, origin.y); |
|
321 |
|
322 nsPresContext* presContext = PresContext(); |
|
323 nsRootPresContext* rpc = presContext->GetRootPresContext(); |
|
324 if (!rpc) { |
|
325 return NS_ERROR_FAILURE; |
|
326 } |
|
327 |
|
328 if (mWidget) { |
|
329 // Disallow windowed plugins in popups |
|
330 nsIFrame* rootFrame = rpc->PresShell()->FrameManager()->GetRootFrame(); |
|
331 nsIWidget* parentWidget = rootFrame->GetNearestWidget(); |
|
332 if (!parentWidget || nsLayoutUtils::GetDisplayRootFrame(this) != rootFrame) { |
|
333 return NS_ERROR_FAILURE; |
|
334 } |
|
335 |
|
336 mInnerView = viewMan->CreateView(GetContentRectRelativeToSelf(), view); |
|
337 if (!mInnerView) { |
|
338 NS_ERROR("Could not create inner view"); |
|
339 return NS_ERROR_OUT_OF_MEMORY; |
|
340 } |
|
341 viewMan->InsertChild(view, mInnerView, nullptr, true); |
|
342 |
|
343 mWidget->SetParent(parentWidget); |
|
344 mWidget->Show(true); |
|
345 mWidget->Enable(true); |
|
346 |
|
347 // Set the plugin window to have an empty clip region until we know |
|
348 // what our true position, size and clip region are. These |
|
349 // will be reset when nsRootPresContext computes our true |
|
350 // geometry. The plugin window does need to have a good size here, so |
|
351 // set the size explicitly to a reasonable guess. |
|
352 nsAutoTArray<nsIWidget::Configuration,1> configurations; |
|
353 nsIWidget::Configuration* configuration = configurations.AppendElement(); |
|
354 nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); |
|
355 configuration->mChild = mWidget; |
|
356 configuration->mBounds.width = NSAppUnitsToIntPixels(mRect.width, appUnitsPerDevPixel); |
|
357 configuration->mBounds.height = NSAppUnitsToIntPixels(mRect.height, appUnitsPerDevPixel); |
|
358 parentWidget->ConfigureChildren(configurations); |
|
359 |
|
360 nsRefPtr<nsDeviceContext> dx = viewMan->GetDeviceContext(); |
|
361 mInnerView->AttachWidgetEventHandler(mWidget); |
|
362 |
|
363 #ifdef XP_MACOSX |
|
364 // On Mac, we need to invalidate ourselves since even windowed |
|
365 // plugins are painted through Thebes and we need to ensure |
|
366 // the Thebes layer containing the plugin is updated. |
|
367 if (parentWidget == GetNearestWidget()) { |
|
368 InvalidateFrame(); |
|
369 } |
|
370 #endif |
|
371 |
|
372 RegisterPluginForGeometryUpdates(); |
|
373 |
|
374 // Here we set the background color for this widget because some plugins will use |
|
375 // the child window background color when painting. If it's not set, it may default to gray |
|
376 // Sometimes, a frame doesn't have a background color or is transparent. In this |
|
377 // case, walk up the frame tree until we do find a frame with a background color |
|
378 for (nsIFrame* frame = this; frame; frame = frame->GetParent()) { |
|
379 nscolor bgcolor = |
|
380 frame->GetVisitedDependentColor(eCSSProperty_background_color); |
|
381 if (NS_GET_A(bgcolor) > 0) { // make sure we got an actual color |
|
382 mWidget->SetBackgroundColor(bgcolor); |
|
383 break; |
|
384 } |
|
385 } |
|
386 } else { |
|
387 // Changing to windowless mode changes the NPWindow geometry. |
|
388 FixupWindow(GetContentRectRelativeToSelf().Size()); |
|
389 |
|
390 #ifndef XP_MACOSX |
|
391 RegisterPluginForGeometryUpdates(); |
|
392 #endif |
|
393 } |
|
394 |
|
395 if (!IsHidden()) { |
|
396 viewMan->SetViewVisibility(view, nsViewVisibility_kShow); |
|
397 } |
|
398 |
|
399 #ifdef ACCESSIBILITY |
|
400 nsAccessibilityService* accService = nsIPresShell::AccService(); |
|
401 if (accService) { |
|
402 accService->RecreateAccessible(PresContext()->PresShell(), mContent); |
|
403 } |
|
404 #endif |
|
405 |
|
406 return NS_OK; |
|
407 } |
|
408 |
|
409 #define EMBED_DEF_WIDTH 240 |
|
410 #define EMBED_DEF_HEIGHT 200 |
|
411 |
|
412 /* virtual */ nscoord |
|
413 nsObjectFrame::GetMinWidth(nsRenderingContext *aRenderingContext) |
|
414 { |
|
415 nscoord result = 0; |
|
416 |
|
417 if (!IsHidden(false)) { |
|
418 nsIAtom *atom = mContent->Tag(); |
|
419 if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) { |
|
420 result = nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH); |
|
421 } |
|
422 } |
|
423 |
|
424 DISPLAY_MIN_WIDTH(this, result); |
|
425 return result; |
|
426 } |
|
427 |
|
428 /* virtual */ nscoord |
|
429 nsObjectFrame::GetPrefWidth(nsRenderingContext *aRenderingContext) |
|
430 { |
|
431 return nsObjectFrame::GetMinWidth(aRenderingContext); |
|
432 } |
|
433 |
|
434 void |
|
435 nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext, |
|
436 const nsHTMLReflowState& aReflowState, |
|
437 nsHTMLReflowMetrics& aMetrics) |
|
438 { |
|
439 // By default, we have no area |
|
440 aMetrics.Width() = 0; |
|
441 aMetrics.Height() = 0; |
|
442 |
|
443 if (IsHidden(false)) { |
|
444 return; |
|
445 } |
|
446 |
|
447 aMetrics.Width() = aReflowState.ComputedWidth(); |
|
448 aMetrics.Height() = aReflowState.ComputedHeight(); |
|
449 |
|
450 // for EMBED and APPLET, default to 240x200 for compatibility |
|
451 nsIAtom *atom = mContent->Tag(); |
|
452 if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) { |
|
453 if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) { |
|
454 aMetrics.Width() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH), |
|
455 aReflowState.ComputedMinWidth(), |
|
456 aReflowState.ComputedMaxWidth()); |
|
457 } |
|
458 if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) { |
|
459 aMetrics.Height() = clamped(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT), |
|
460 aReflowState.ComputedMinHeight(), |
|
461 aReflowState.ComputedMaxHeight()); |
|
462 } |
|
463 |
|
464 #if defined(MOZ_WIDGET_GTK) |
|
465 // We need to make sure that the size of the object frame does not |
|
466 // exceed the maximum size of X coordinates. See bug #225357 for |
|
467 // more information. In theory Gtk2 can handle large coordinates, |
|
468 // but underlying plugins can't. |
|
469 aMetrics.Height() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Height()); |
|
470 aMetrics.Width() = std::min(aPresContext->DevPixelsToAppUnits(INT16_MAX), aMetrics.Width()); |
|
471 #endif |
|
472 } |
|
473 |
|
474 // At this point, the width has an unconstrained value only if we have |
|
475 // nothing to go on (no width set, no information from the plugin, nothing). |
|
476 // Make up a number. |
|
477 if (aMetrics.Width() == NS_UNCONSTRAINEDSIZE) { |
|
478 aMetrics.Width() = |
|
479 (aReflowState.ComputedMinWidth() != NS_UNCONSTRAINEDSIZE) ? |
|
480 aReflowState.ComputedMinWidth() : 0; |
|
481 } |
|
482 |
|
483 // At this point, the height has an unconstrained value only in two cases: |
|
484 // a) We are in standards mode with percent heights and parent is auto-height |
|
485 // b) We have no height information at all. |
|
486 // In either case, we have to make up a number. |
|
487 if (aMetrics.Height() == NS_UNCONSTRAINEDSIZE) { |
|
488 aMetrics.Height() = |
|
489 (aReflowState.ComputedMinHeight() != NS_UNCONSTRAINEDSIZE) ? |
|
490 aReflowState.ComputedMinHeight() : 0; |
|
491 } |
|
492 |
|
493 // XXXbz don't add in the border and padding, because we screw up our |
|
494 // plugin's size and positioning if we do... Eventually we _do_ want to |
|
495 // paint borders, though! At that point, we will need to adjust the desired |
|
496 // size either here or in Reflow.... Further, we will need to fix Paint() to |
|
497 // call the superclass in all cases. |
|
498 } |
|
499 |
|
500 nsresult |
|
501 nsObjectFrame::Reflow(nsPresContext* aPresContext, |
|
502 nsHTMLReflowMetrics& aMetrics, |
|
503 const nsHTMLReflowState& aReflowState, |
|
504 nsReflowStatus& aStatus) |
|
505 { |
|
506 DO_GLOBAL_REFLOW_COUNT("nsObjectFrame"); |
|
507 DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); |
|
508 |
|
509 // Get our desired size |
|
510 GetDesiredSize(aPresContext, aReflowState, aMetrics); |
|
511 aMetrics.SetOverflowAreasToDesiredBounds(); |
|
512 FinishAndStoreOverflow(&aMetrics); |
|
513 |
|
514 // delay plugin instantiation until all children have |
|
515 // arrived. Otherwise there may be PARAMs or other stuff that the |
|
516 // plugin needs to see that haven't arrived yet. |
|
517 if (!GetContent()->IsDoneAddingChildren()) { |
|
518 aStatus = NS_FRAME_COMPLETE; |
|
519 return NS_OK; |
|
520 } |
|
521 |
|
522 // if we are printing or print previewing, bail for now |
|
523 if (aPresContext->Medium() == nsGkAtoms::print) { |
|
524 aStatus = NS_FRAME_COMPLETE; |
|
525 return NS_OK; |
|
526 } |
|
527 |
|
528 nsRect r(0, 0, aMetrics.Width(), aMetrics.Height()); |
|
529 r.Deflate(aReflowState.ComputedPhysicalBorderPadding()); |
|
530 |
|
531 if (mInnerView) { |
|
532 nsViewManager* vm = mInnerView->GetViewManager(); |
|
533 vm->MoveViewTo(mInnerView, r.x, r.y); |
|
534 vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), r.Size()), true); |
|
535 } |
|
536 |
|
537 FixupWindow(r.Size()); |
|
538 if (!mReflowCallbackPosted) { |
|
539 mReflowCallbackPosted = true; |
|
540 aPresContext->PresShell()->PostReflowCallback(this); |
|
541 } |
|
542 |
|
543 aStatus = NS_FRAME_COMPLETE; |
|
544 |
|
545 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics); |
|
546 return NS_OK; |
|
547 } |
|
548 |
|
549 ///////////// nsIReflowCallback /////////////// |
|
550 |
|
551 bool |
|
552 nsObjectFrame::ReflowFinished() |
|
553 { |
|
554 mReflowCallbackPosted = false; |
|
555 CallSetWindow(); |
|
556 return true; |
|
557 } |
|
558 |
|
559 void |
|
560 nsObjectFrame::ReflowCallbackCanceled() |
|
561 { |
|
562 mReflowCallbackPosted = false; |
|
563 } |
|
564 |
|
565 void |
|
566 nsObjectFrame::FixupWindow(const nsSize& aSize) |
|
567 { |
|
568 nsPresContext* presContext = PresContext(); |
|
569 |
|
570 if (!mInstanceOwner) |
|
571 return; |
|
572 |
|
573 NPWindow *window; |
|
574 mInstanceOwner->GetWindow(window); |
|
575 |
|
576 NS_ENSURE_TRUE_VOID(window); |
|
577 |
|
578 #ifdef XP_MACOSX |
|
579 nsWeakFrame weakFrame(this); |
|
580 mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable); |
|
581 if (!weakFrame.IsAlive()) { |
|
582 return; |
|
583 } |
|
584 #endif |
|
585 |
|
586 bool windowless = (window->type == NPWindowTypeDrawable); |
|
587 |
|
588 nsIntPoint origin = GetWindowOriginInPixels(windowless); |
|
589 |
|
590 // window must be in "display pixels" |
|
591 double scaleFactor = 1.0; |
|
592 if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) { |
|
593 scaleFactor = 1.0; |
|
594 } |
|
595 int intScaleFactor = ceil(scaleFactor); |
|
596 window->x = origin.x / intScaleFactor; |
|
597 window->y = origin.y / intScaleFactor; |
|
598 window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor; |
|
599 window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor; |
|
600 |
|
601 // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep |
|
602 // us from drawing on screen until the widget is properly positioned, which will not |
|
603 // happen until we have finished the reflow process. |
|
604 #ifdef XP_MACOSX |
|
605 window->clipRect.top = 0; |
|
606 window->clipRect.left = 0; |
|
607 window->clipRect.bottom = 0; |
|
608 window->clipRect.right = 0; |
|
609 #else |
|
610 mInstanceOwner->UpdateWindowPositionAndClipRect(false); |
|
611 #endif |
|
612 |
|
613 NotifyPluginReflowObservers(); |
|
614 } |
|
615 |
|
616 nsresult |
|
617 nsObjectFrame::CallSetWindow(bool aCheckIsHidden) |
|
618 { |
|
619 NPWindow *win = nullptr; |
|
620 |
|
621 nsresult rv = NS_ERROR_FAILURE; |
|
622 nsRefPtr<nsNPAPIPluginInstance> pi; |
|
623 if (!mInstanceOwner || |
|
624 NS_FAILED(rv = mInstanceOwner->GetInstance(getter_AddRefs(pi))) || |
|
625 !pi || |
|
626 NS_FAILED(rv = mInstanceOwner->GetWindow(win)) || |
|
627 !win) |
|
628 return rv; |
|
629 |
|
630 nsPluginNativeWindow *window = (nsPluginNativeWindow *)win; |
|
631 #ifdef XP_MACOSX |
|
632 nsWeakFrame weakFrame(this); |
|
633 mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable); |
|
634 if (!weakFrame.IsAlive()) { |
|
635 return NS_ERROR_NOT_AVAILABLE; |
|
636 } |
|
637 #endif |
|
638 |
|
639 if (aCheckIsHidden && IsHidden()) |
|
640 return NS_ERROR_FAILURE; |
|
641 |
|
642 // refresh the plugin port as well |
|
643 window->window = mInstanceOwner->GetPluginPortFromWidget(); |
|
644 |
|
645 // Adjust plugin dimensions according to pixel snap results |
|
646 // and reduce amount of SetWindow calls |
|
647 nsPresContext* presContext = PresContext(); |
|
648 nsRootPresContext* rootPC = presContext->GetRootPresContext(); |
|
649 if (!rootPC) |
|
650 return NS_ERROR_FAILURE; |
|
651 int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); |
|
652 nsIFrame* rootFrame = rootPC->PresShell()->FrameManager()->GetRootFrame(); |
|
653 nsRect bounds = GetContentRectRelativeToSelf() + GetOffsetToCrossDoc(rootFrame); |
|
654 nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel); |
|
655 |
|
656 // window must be in "display pixels" |
|
657 double scaleFactor = 1.0; |
|
658 if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) { |
|
659 scaleFactor = 1.0; |
|
660 } |
|
661 size_t intScaleFactor = ceil(scaleFactor); |
|
662 window->x = intBounds.x / intScaleFactor; |
|
663 window->y = intBounds.y / intScaleFactor; |
|
664 window->width = intBounds.width / intScaleFactor; |
|
665 window->height = intBounds.height / intScaleFactor; |
|
666 |
|
667 // Calling SetWindow might destroy this frame. We need to use the instance |
|
668 // owner to clean up so hold a ref. |
|
669 nsRefPtr<nsPluginInstanceOwner> instanceOwnerRef(mInstanceOwner); |
|
670 |
|
671 // This will call pi->SetWindow and take care of window subclassing |
|
672 // if needed, see bug 132759. Calling SetWindow can destroy this frame |
|
673 // so check for that before doing anything else with this frame's memory. |
|
674 if (mInstanceOwner->UseAsyncRendering()) { |
|
675 rv = pi->AsyncSetWindow(window); |
|
676 } |
|
677 else { |
|
678 rv = window->CallSetWindow(pi); |
|
679 } |
|
680 |
|
681 instanceOwnerRef->ReleasePluginPort(window->window); |
|
682 |
|
683 return rv; |
|
684 } |
|
685 |
|
686 void |
|
687 nsObjectFrame::RegisterPluginForGeometryUpdates() |
|
688 { |
|
689 nsRootPresContext* rpc = PresContext()->GetRootPresContext(); |
|
690 NS_ASSERTION(rpc, "We should have a root pres context!"); |
|
691 if (mRootPresContextRegisteredWith == rpc || !rpc) { |
|
692 // Already registered with current root pres context, |
|
693 // or null root pres context... |
|
694 return; |
|
695 } |
|
696 if (mRootPresContextRegisteredWith && mRootPresContextRegisteredWith != rpc) { |
|
697 // Registered to some other root pres context. Unregister, and |
|
698 // re-register with our current one... |
|
699 UnregisterPluginForGeometryUpdates(); |
|
700 } |
|
701 mRootPresContextRegisteredWith = rpc; |
|
702 mRootPresContextRegisteredWith->RegisterPluginForGeometryUpdates(mContent); |
|
703 } |
|
704 |
|
705 void |
|
706 nsObjectFrame::UnregisterPluginForGeometryUpdates() |
|
707 { |
|
708 if (!mRootPresContextRegisteredWith) { |
|
709 // Not registered... |
|
710 return; |
|
711 } |
|
712 mRootPresContextRegisteredWith->UnregisterPluginForGeometryUpdates(mContent); |
|
713 mRootPresContextRegisteredWith = nullptr; |
|
714 } |
|
715 |
|
716 void |
|
717 nsObjectFrame::SetInstanceOwner(nsPluginInstanceOwner* aOwner) |
|
718 { |
|
719 // The ownership model here is historically fuzzy. This should only be called |
|
720 // by nsPluginInstanceOwner when it is given a new frame, and |
|
721 // nsObjectLoadingContent should be arbitrating frame-ownership via its |
|
722 // HasNewFrame callback. |
|
723 mInstanceOwner = aOwner; |
|
724 if (mInstanceOwner) { |
|
725 return; |
|
726 } |
|
727 UnregisterPluginForGeometryUpdates(); |
|
728 if (mWidget && mInnerView) { |
|
729 mInnerView->DetachWidgetEventHandler(mWidget); |
|
730 // Make sure the plugin is hidden in case an update of plugin geometry |
|
731 // hasn't happened since this plugin became hidden. |
|
732 nsIWidget* parent = mWidget->GetParent(); |
|
733 if (parent) { |
|
734 nsTArray<nsIWidget::Configuration> configurations; |
|
735 nsIWidget::Configuration* configuration = configurations.AppendElement(); |
|
736 configuration->mChild = mWidget; |
|
737 parent->ConfigureChildren(configurations); |
|
738 |
|
739 mWidget->Show(false); |
|
740 mWidget->Enable(false); |
|
741 mWidget->SetParent(nullptr); |
|
742 } |
|
743 } |
|
744 } |
|
745 |
|
746 bool |
|
747 nsObjectFrame::IsFocusable(int32_t *aTabIndex, bool aWithMouse) |
|
748 { |
|
749 if (aTabIndex) |
|
750 *aTabIndex = -1; |
|
751 return nsObjectFrameSuper::IsFocusable(aTabIndex, aWithMouse); |
|
752 } |
|
753 |
|
754 bool |
|
755 nsObjectFrame::IsHidden(bool aCheckVisibilityStyle) const |
|
756 { |
|
757 if (aCheckVisibilityStyle) { |
|
758 if (!StyleVisibility()->IsVisibleOrCollapsed()) |
|
759 return true; |
|
760 } |
|
761 |
|
762 // only <embed> tags support the HIDDEN attribute |
|
763 if (mContent->Tag() == nsGkAtoms::embed) { |
|
764 // Yes, these are really the kooky ways that you could tell 4.x |
|
765 // not to hide the <embed> once you'd put the 'hidden' attribute |
|
766 // on the tag... |
|
767 |
|
768 // HIDDEN w/ no attributes gets translated as we are hidden for |
|
769 // compatibility w/ 4.x and IE so we don't create a non-painting |
|
770 // widget in layout. See bug 188959. |
|
771 nsAutoString hidden; |
|
772 if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::hidden, hidden) && |
|
773 (hidden.IsEmpty() || |
|
774 (!hidden.LowerCaseEqualsLiteral("false") && |
|
775 !hidden.LowerCaseEqualsLiteral("no") && |
|
776 !hidden.LowerCaseEqualsLiteral("off")))) { |
|
777 return true; |
|
778 } |
|
779 } |
|
780 |
|
781 return false; |
|
782 } |
|
783 |
|
784 nsIntPoint nsObjectFrame::GetWindowOriginInPixels(bool aWindowless) |
|
785 { |
|
786 nsView * parentWithView; |
|
787 nsPoint origin(0,0); |
|
788 |
|
789 GetOffsetFromView(origin, &parentWithView); |
|
790 |
|
791 // if it's windowless, let's make sure we have our origin set right |
|
792 // it may need to be corrected, like after scrolling |
|
793 if (aWindowless && parentWithView) { |
|
794 nsPoint offsetToWidget; |
|
795 parentWithView->GetNearestWidget(&offsetToWidget); |
|
796 origin += offsetToWidget; |
|
797 } |
|
798 origin += GetContentRectRelativeToSelf().TopLeft(); |
|
799 |
|
800 return nsIntPoint(PresContext()->AppUnitsToDevPixels(origin.x), |
|
801 PresContext()->AppUnitsToDevPixels(origin.y)); |
|
802 } |
|
803 |
|
804 nsresult |
|
805 nsObjectFrame::DidReflow(nsPresContext* aPresContext, |
|
806 const nsHTMLReflowState* aReflowState, |
|
807 nsDidReflowStatus aStatus) |
|
808 { |
|
809 // Do this check before calling the superclass, as that clears |
|
810 // NS_FRAME_FIRST_REFLOW |
|
811 if (aStatus == nsDidReflowStatus::FINISHED && |
|
812 (GetStateBits() & NS_FRAME_FIRST_REFLOW)) { |
|
813 nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent)); |
|
814 NS_ASSERTION(objContent, "Why not an object loading content?"); |
|
815 objContent->HasNewFrame(this); |
|
816 } |
|
817 |
|
818 nsresult rv = nsObjectFrameSuper::DidReflow(aPresContext, aReflowState, aStatus); |
|
819 |
|
820 // The view is created hidden; once we have reflowed it and it has been |
|
821 // positioned then we show it. |
|
822 if (aStatus != nsDidReflowStatus::FINISHED) |
|
823 return rv; |
|
824 |
|
825 if (HasView()) { |
|
826 nsView* view = GetView(); |
|
827 nsViewManager* vm = view->GetViewManager(); |
|
828 if (vm) |
|
829 vm->SetViewVisibility(view, IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow); |
|
830 } |
|
831 |
|
832 return rv; |
|
833 } |
|
834 |
|
835 /* static */ void |
|
836 nsObjectFrame::PaintPrintPlugin(nsIFrame* aFrame, nsRenderingContext* aCtx, |
|
837 const nsRect& aDirtyRect, nsPoint aPt) |
|
838 { |
|
839 nsPoint pt = aPt + aFrame->GetContentRectRelativeToSelf().TopLeft(); |
|
840 nsRenderingContext::AutoPushTranslation translate(aCtx, pt); |
|
841 // FIXME - Bug 385435: Doesn't aDirtyRect need translating too? |
|
842 static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect); |
|
843 } |
|
844 |
|
845 class nsDisplayPluginReadback : public nsDisplayItem { |
|
846 public: |
|
847 nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) |
|
848 : nsDisplayItem(aBuilder, aFrame) |
|
849 { |
|
850 MOZ_COUNT_CTOR(nsDisplayPluginReadback); |
|
851 } |
|
852 #ifdef NS_BUILD_REFCNT_LOGGING |
|
853 virtual ~nsDisplayPluginReadback() { |
|
854 MOZ_COUNT_DTOR(nsDisplayPluginReadback); |
|
855 } |
|
856 #endif |
|
857 |
|
858 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, |
|
859 bool* aSnap) MOZ_OVERRIDE; |
|
860 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
861 nsRegion* aVisibleRegion, |
|
862 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
863 |
|
864 NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK) |
|
865 |
|
866 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
867 LayerManager* aManager, |
|
868 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE |
|
869 { |
|
870 return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters); |
|
871 } |
|
872 |
|
873 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
874 LayerManager* aManager, |
|
875 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE |
|
876 { |
|
877 return LAYER_ACTIVE; |
|
878 } |
|
879 }; |
|
880 |
|
881 static nsRect |
|
882 GetDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame) |
|
883 { |
|
884 // XXX For slightly more accurate region computations we should pixel-snap this |
|
885 return aFrame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame(); |
|
886 } |
|
887 |
|
888 nsRect |
|
889 nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) |
|
890 { |
|
891 *aSnap = false; |
|
892 return GetDisplayItemBounds(aBuilder, this, mFrame); |
|
893 } |
|
894 |
|
895 bool |
|
896 nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
897 nsRegion* aVisibleRegion, |
|
898 const nsRect& aAllowVisibleRegionExpansion) |
|
899 { |
|
900 if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, |
|
901 aAllowVisibleRegionExpansion)) |
|
902 return false; |
|
903 |
|
904 nsRect expand; |
|
905 bool snap; |
|
906 expand.IntersectRect(aAllowVisibleRegionExpansion, GetBounds(aBuilder, &snap)); |
|
907 // *Add* our bounds to the visible region so that stuff underneath us is |
|
908 // likely to be made visible, so we can use it for a background! This is |
|
909 // a bit crazy since we normally only subtract from the visible region. |
|
910 aVisibleRegion->Or(*aVisibleRegion, expand); |
|
911 return true; |
|
912 } |
|
913 |
|
914 #ifdef MOZ_WIDGET_ANDROID |
|
915 |
|
916 class nsDisplayPluginVideo : public nsDisplayItem { |
|
917 public: |
|
918 nsDisplayPluginVideo(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsNPAPIPluginInstance::VideoInfo* aVideoInfo) |
|
919 : nsDisplayItem(aBuilder, aFrame), mVideoInfo(aVideoInfo) |
|
920 { |
|
921 MOZ_COUNT_CTOR(nsDisplayPluginVideo); |
|
922 } |
|
923 #ifdef NS_BUILD_REFCNT_LOGGING |
|
924 virtual ~nsDisplayPluginVideo() { |
|
925 MOZ_COUNT_DTOR(nsDisplayPluginVideo); |
|
926 } |
|
927 #endif |
|
928 |
|
929 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, |
|
930 bool* aSnap) MOZ_OVERRIDE; |
|
931 virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
932 nsRegion* aVisibleRegion, |
|
933 const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; |
|
934 |
|
935 NS_DISPLAY_DECL_NAME("PluginVideo", TYPE_PLUGIN_VIDEO) |
|
936 |
|
937 virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, |
|
938 LayerManager* aManager, |
|
939 const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE |
|
940 { |
|
941 return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters); |
|
942 } |
|
943 |
|
944 virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, |
|
945 LayerManager* aManager, |
|
946 const ContainerLayerParameters& aParameters) MOZ_OVERRIDE |
|
947 { |
|
948 return LAYER_ACTIVE; |
|
949 } |
|
950 |
|
951 nsNPAPIPluginInstance::VideoInfo* VideoInfo() { return mVideoInfo; } |
|
952 |
|
953 private: |
|
954 nsNPAPIPluginInstance::VideoInfo* mVideoInfo; |
|
955 }; |
|
956 |
|
957 nsRect |
|
958 nsDisplayPluginVideo::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) |
|
959 { |
|
960 *aSnap = false; |
|
961 return GetDisplayItemBounds(aBuilder, this, mFrame); |
|
962 } |
|
963 |
|
964 bool |
|
965 nsDisplayPluginVideo::ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
966 nsRegion* aVisibleRegion, |
|
967 const nsRect& aAllowVisibleRegionExpansion) |
|
968 { |
|
969 return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, |
|
970 aAllowVisibleRegionExpansion); |
|
971 } |
|
972 |
|
973 #endif |
|
974 |
|
975 nsRect |
|
976 nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) |
|
977 { |
|
978 *aSnap = true; |
|
979 return GetDisplayItemBounds(aBuilder, this, mFrame); |
|
980 } |
|
981 |
|
982 void |
|
983 nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder, |
|
984 nsRenderingContext* aCtx) |
|
985 { |
|
986 nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame); |
|
987 bool snap; |
|
988 f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder, &snap)); |
|
989 } |
|
990 |
|
991 bool |
|
992 nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder, |
|
993 nsRegion* aVisibleRegion, |
|
994 const nsRect& aAllowVisibleRegionExpansion) |
|
995 { |
|
996 if (aBuilder->IsForPluginGeometry()) { |
|
997 nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame); |
|
998 if (!aBuilder->IsInTransform() || f->IsPaintedByGecko()) { |
|
999 // Since transforms induce reference frames, we don't need to worry |
|
1000 // about this method fluffing out due to non-rectilinear transforms. |
|
1001 nsRect rAncestor = nsLayoutUtils::TransformFrameRectToAncestor(f, |
|
1002 f->GetContentRectRelativeToSelf(), ReferenceFrame()); |
|
1003 nscoord appUnitsPerDevPixel = |
|
1004 ReferenceFrame()->PresContext()->AppUnitsPerDevPixel(); |
|
1005 f->mNextConfigurationBounds = rAncestor.ToNearestPixels(appUnitsPerDevPixel); |
|
1006 |
|
1007 nsRegion visibleRegion; |
|
1008 visibleRegion.And(*aVisibleRegion, GetClippedBounds(aBuilder)); |
|
1009 // Make visibleRegion relative to f |
|
1010 visibleRegion.MoveBy(-ToReferenceFrame()); |
|
1011 |
|
1012 f->mNextConfigurationClipRegion.Clear(); |
|
1013 nsRegionRectIterator iter(visibleRegion); |
|
1014 for (const nsRect* r = iter.Next(); r; r = iter.Next()) { |
|
1015 nsRect rAncestor = |
|
1016 nsLayoutUtils::TransformFrameRectToAncestor(f, *r, ReferenceFrame()); |
|
1017 nsIntRect rPixels = rAncestor.ToNearestPixels(appUnitsPerDevPixel) |
|
1018 - f->mNextConfigurationBounds.TopLeft(); |
|
1019 if (!rPixels.IsEmpty()) { |
|
1020 f->mNextConfigurationClipRegion.AppendElement(rPixels); |
|
1021 } |
|
1022 } |
|
1023 } |
|
1024 |
|
1025 if (f->mInnerView) { |
|
1026 // This should produce basically the same rectangle (but not relative |
|
1027 // to the root frame). We only call this here for the side-effect of |
|
1028 // setting mViewToWidgetOffset on the view. |
|
1029 f->mInnerView->CalcWidgetBounds(eWindowType_plugin); |
|
1030 } |
|
1031 } |
|
1032 |
|
1033 return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, |
|
1034 aAllowVisibleRegionExpansion); |
|
1035 } |
|
1036 |
|
1037 nsRegion |
|
1038 nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder, |
|
1039 bool* aSnap) |
|
1040 { |
|
1041 *aSnap = false; |
|
1042 nsRegion result; |
|
1043 nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame); |
|
1044 if (!aBuilder->IsForPluginGeometry()) { |
|
1045 nsIWidget* widget = f->GetWidget(); |
|
1046 if (widget) { |
|
1047 // Be conservative and treat plugins with widgets as not opaque, |
|
1048 // because that's simple and we might need the content under the widget |
|
1049 // if the widget is unexpectedly clipped away. (As can happen when |
|
1050 // chrome content over a plugin forces us to clip out the plugin for |
|
1051 // security reasons.) |
|
1052 // We shouldn't be repainting the content under plugins much anyway |
|
1053 // since there generally shouldn't be anything to invalidate or paint |
|
1054 // in ThebesLayers there. |
|
1055 return result; |
|
1056 } |
|
1057 } |
|
1058 |
|
1059 if (f->IsOpaque()) { |
|
1060 nsRect bounds = GetBounds(aBuilder, aSnap); |
|
1061 if (aBuilder->IsForPluginGeometry() || |
|
1062 (f->GetPaintedRect(this) + ToReferenceFrame()).Contains(bounds)) { |
|
1063 // We can treat this as opaque |
|
1064 result = bounds; |
|
1065 } |
|
1066 } |
|
1067 |
|
1068 return result; |
|
1069 } |
|
1070 |
|
1071 nsresult |
|
1072 nsObjectFrame::PluginEventNotifier::Run() { |
|
1073 nsCOMPtr<nsIObserverService> obsSvc = |
|
1074 mozilla::services::GetObserverService(); |
|
1075 obsSvc->NotifyObservers(nullptr, "plugin-changed-event", mEventType.get()); |
|
1076 return NS_OK; |
|
1077 } |
|
1078 |
|
1079 void |
|
1080 nsObjectFrame::NotifyPluginReflowObservers() |
|
1081 { |
|
1082 nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow"))); |
|
1083 } |
|
1084 |
|
1085 void |
|
1086 nsObjectFrame::DidSetWidgetGeometry() |
|
1087 { |
|
1088 #if defined(XP_MACOSX) |
|
1089 if (mInstanceOwner) { |
|
1090 mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable); |
|
1091 } |
|
1092 #else |
|
1093 if (!mWidget && mInstanceOwner) { |
|
1094 // UpdateWindowVisibility will notify the plugin of position changes |
|
1095 // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow. |
|
1096 // We treat windowless plugins inside popups as always visible, since |
|
1097 // plugins inside popups don't get valid mNextConfigurationBounds |
|
1098 // set up. |
|
1099 mInstanceOwner->UpdateWindowVisibility( |
|
1100 nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) || |
|
1101 !mNextConfigurationBounds.IsEmpty()); |
|
1102 } |
|
1103 #endif |
|
1104 } |
|
1105 |
|
1106 bool |
|
1107 nsObjectFrame::IsOpaque() const |
|
1108 { |
|
1109 #if defined(XP_MACOSX) |
|
1110 // ??? |
|
1111 return false; |
|
1112 #elif defined(MOZ_WIDGET_ANDROID) |
|
1113 // We don't know, so just assume transparent |
|
1114 return false; |
|
1115 #else |
|
1116 return !IsTransparentMode(); |
|
1117 #endif |
|
1118 } |
|
1119 |
|
1120 bool |
|
1121 nsObjectFrame::IsTransparentMode() const |
|
1122 { |
|
1123 #if defined(XP_MACOSX) |
|
1124 // ??? |
|
1125 return false; |
|
1126 #else |
|
1127 if (!mInstanceOwner) |
|
1128 return false; |
|
1129 |
|
1130 NPWindow *window = nullptr; |
|
1131 mInstanceOwner->GetWindow(window); |
|
1132 if (!window) { |
|
1133 return false; |
|
1134 } |
|
1135 |
|
1136 if (window->type != NPWindowTypeDrawable) |
|
1137 return false; |
|
1138 |
|
1139 nsresult rv; |
|
1140 nsRefPtr<nsNPAPIPluginInstance> pi; |
|
1141 rv = mInstanceOwner->GetInstance(getter_AddRefs(pi)); |
|
1142 if (NS_FAILED(rv) || !pi) |
|
1143 return false; |
|
1144 |
|
1145 bool transparent = false; |
|
1146 pi->IsTransparent(&transparent); |
|
1147 return transparent; |
|
1148 #endif |
|
1149 } |
|
1150 |
|
1151 void |
|
1152 nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, |
|
1153 const nsRect& aDirtyRect, |
|
1154 const nsDisplayListSet& aLists) |
|
1155 { |
|
1156 // XXX why are we painting collapsed object frames? |
|
1157 if (!IsVisibleOrCollapsedForPainting(aBuilder)) |
|
1158 return; |
|
1159 |
|
1160 DisplayBorderBackgroundOutline(aBuilder, aLists); |
|
1161 |
|
1162 nsPresContext::nsPresContextType type = PresContext()->Type(); |
|
1163 |
|
1164 // If we are painting in Print Preview do nothing.... |
|
1165 if (type == nsPresContext::eContext_PrintPreview) |
|
1166 return; |
|
1167 |
|
1168 DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame"); |
|
1169 |
|
1170 #ifndef XP_MACOSX |
|
1171 if (mWidget && aBuilder->IsInTransform()) { |
|
1172 // Windowed plugins should not be rendered inside a transform. |
|
1173 return; |
|
1174 } |
|
1175 #endif |
|
1176 |
|
1177 if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) { |
|
1178 NPWindow* window = nullptr; |
|
1179 mInstanceOwner->GetWindow(window); |
|
1180 bool isVisible = window && window->width > 0 && window->height > 0; |
|
1181 if (isVisible && aBuilder->ShouldSyncDecodeImages()) { |
|
1182 #ifndef XP_MACOSX |
|
1183 mInstanceOwner->UpdateWindowVisibility(true); |
|
1184 #endif |
|
1185 } |
|
1186 |
|
1187 mInstanceOwner->NotifyPaintWaiter(aBuilder); |
|
1188 } |
|
1189 |
|
1190 DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox |
|
1191 clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT); |
|
1192 |
|
1193 // determine if we are printing |
|
1194 if (type == nsPresContext::eContext_Print) { |
|
1195 aLists.Content()->AppendNewToTop(new (aBuilder) |
|
1196 nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin", |
|
1197 nsDisplayItem::TYPE_PRINT_PLUGIN)); |
|
1198 } else { |
|
1199 LayerState state = GetLayerState(aBuilder, nullptr); |
|
1200 if (state == LAYER_INACTIVE && |
|
1201 nsDisplayItem::ForceActiveLayers()) { |
|
1202 state = LAYER_ACTIVE; |
|
1203 } |
|
1204 // We don't need this on Android, and it just confuses things |
|
1205 #if !MOZ_WIDGET_ANDROID |
|
1206 if (aBuilder->IsPaintingToWindow() && |
|
1207 state == LAYER_ACTIVE && |
|
1208 IsTransparentMode()) { |
|
1209 aLists.Content()->AppendNewToTop(new (aBuilder) |
|
1210 nsDisplayPluginReadback(aBuilder, this)); |
|
1211 } |
|
1212 #endif |
|
1213 |
|
1214 #if MOZ_WIDGET_ANDROID |
|
1215 if (aBuilder->IsPaintingToWindow() && |
|
1216 state == LAYER_ACTIVE) { |
|
1217 |
|
1218 nsTArray<nsNPAPIPluginInstance::VideoInfo*> videos; |
|
1219 mInstanceOwner->GetVideos(videos); |
|
1220 |
|
1221 for (uint32_t i = 0; i < videos.Length(); i++) { |
|
1222 aLists.Content()->AppendNewToTop(new (aBuilder) |
|
1223 nsDisplayPluginVideo(aBuilder, this, videos[i])); |
|
1224 } |
|
1225 } |
|
1226 #endif |
|
1227 |
|
1228 aLists.Content()->AppendNewToTop(new (aBuilder) |
|
1229 nsDisplayPlugin(aBuilder, this)); |
|
1230 } |
|
1231 } |
|
1232 |
|
1233 void |
|
1234 nsObjectFrame::PrintPlugin(nsRenderingContext& aRenderingContext, |
|
1235 const nsRect& aDirtyRect) |
|
1236 { |
|
1237 nsCOMPtr<nsIObjectLoadingContent> obj(do_QueryInterface(mContent)); |
|
1238 if (!obj) |
|
1239 return; |
|
1240 |
|
1241 nsIFrame* frame = nullptr; |
|
1242 obj->GetPrintFrame(&frame); |
|
1243 if (!frame) |
|
1244 return; |
|
1245 |
|
1246 nsPresContext* presContext = PresContext(); |
|
1247 // make sure this is REALLY an nsIObjectFrame |
|
1248 // we may need to go through the children to get it |
|
1249 nsIObjectFrame* objectFrame = do_QueryFrame(frame); |
|
1250 if (!objectFrame) |
|
1251 objectFrame = GetNextObjectFrame(presContext,frame); |
|
1252 if (!objectFrame) |
|
1253 return; |
|
1254 |
|
1255 // finally we can get our plugin instance |
|
1256 nsRefPtr<nsNPAPIPluginInstance> pi; |
|
1257 if (NS_FAILED(objectFrame->GetPluginInstance(getter_AddRefs(pi))) || !pi) |
|
1258 return; |
|
1259 |
|
1260 // now we need to setup the correct location for printing |
|
1261 NPWindow window; |
|
1262 window.window = nullptr; |
|
1263 |
|
1264 // prepare embedded mode printing struct |
|
1265 NPPrint npprint; |
|
1266 npprint.mode = NP_EMBED; |
|
1267 |
|
1268 // we need to find out if we are windowless or not |
|
1269 bool windowless = false; |
|
1270 pi->IsWindowless(&windowless); |
|
1271 window.type = windowless ? NPWindowTypeDrawable : NPWindowTypeWindow; |
|
1272 |
|
1273 window.clipRect.bottom = 0; window.clipRect.top = 0; |
|
1274 window.clipRect.left = 0; window.clipRect.right = 0; |
|
1275 |
|
1276 // platform specific printing code |
|
1277 #if defined(XP_MACOSX) && !defined(__LP64__) |
|
1278 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
|
1279 // Don't use this code if any of the QuickDraw APIs it currently requires |
|
1280 // are missing (as they probably will be on OS X 10.8 and up). |
|
1281 if (!&::SetRect || !&::NewGWorldFromPtr || !&::DisposeGWorld) { |
|
1282 NS_WARNING("Cannot print plugin -- required QuickDraw APIs are missing!"); |
|
1283 return; |
|
1284 } |
|
1285 |
|
1286 nsSize contentSize = GetContentRectRelativeToSelf().Size(); |
|
1287 window.x = 0; |
|
1288 window.y = 0; |
|
1289 window.width = presContext->AppUnitsToDevPixels(contentSize.width); |
|
1290 window.height = presContext->AppUnitsToDevPixels(contentSize.height); |
|
1291 |
|
1292 gfxContext *ctx = aRenderingContext.ThebesContext(); |
|
1293 if (!ctx) |
|
1294 return; |
|
1295 gfxContextAutoSaveRestore save(ctx); |
|
1296 |
|
1297 ctx->NewPath(); |
|
1298 |
|
1299 gfxRect rect(window.x, window.y, window.width, window.height); |
|
1300 |
|
1301 ctx->Rectangle(rect); |
|
1302 ctx->Clip(); |
|
1303 |
|
1304 gfxQuartzNativeDrawing nativeDraw(ctx, rect); |
|
1305 CGContextRef cgContext = nativeDraw.BeginNativeDrawing(); |
|
1306 if (!cgContext) { |
|
1307 nativeDraw.EndNativeDrawing(); |
|
1308 return; |
|
1309 } |
|
1310 |
|
1311 window.clipRect.right = window.width; |
|
1312 window.clipRect.bottom = window.height; |
|
1313 window.type = NPWindowTypeDrawable; |
|
1314 |
|
1315 ::Rect gwBounds; |
|
1316 ::SetRect(&gwBounds, 0, 0, window.width, window.height); |
|
1317 |
|
1318 nsTArray<char> buffer(window.width * window.height * 4); |
|
1319 CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); |
|
1320 if (!cspace) { |
|
1321 nativeDraw.EndNativeDrawing(); |
|
1322 return; |
|
1323 } |
|
1324 CGContextRef cgBuffer = |
|
1325 ::CGBitmapContextCreate(buffer.Elements(), |
|
1326 window.width, window.height, 8, window.width * 4, |
|
1327 cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst); |
|
1328 ::CGColorSpaceRelease(cspace); |
|
1329 if (!cgBuffer) { |
|
1330 nativeDraw.EndNativeDrawing(); |
|
1331 return; |
|
1332 } |
|
1333 GWorldPtr gWorld; |
|
1334 if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds, |
|
1335 nullptr, nullptr, 0, |
|
1336 buffer.Elements(), window.width * 4) != noErr) { |
|
1337 ::CGContextRelease(cgBuffer); |
|
1338 nativeDraw.EndNativeDrawing(); |
|
1339 return; |
|
1340 } |
|
1341 |
|
1342 window.clipRect.right = window.width; |
|
1343 window.clipRect.bottom = window.height; |
|
1344 window.type = NPWindowTypeDrawable; |
|
1345 // Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to |
|
1346 // &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to |
|
1347 // GWorldPtr isn't any kind of standard (it's not documented anywhere). |
|
1348 // But that's what WebKit does. And it's what the Flash plugin (apparently |
|
1349 // the only NPAPI plugin on OS X to support printing) seems to expect. So |
|
1350 // we do the same. The Flash plugin uses the CoreGraphics drawing mode. |
|
1351 // But a GWorldPtr should be usable in either CoreGraphics or QuickDraw |
|
1352 // drawing mode. See bug 191046. |
|
1353 window.window = &gWorld; |
|
1354 npprint.print.embedPrint.platformPrint = gWorld; |
|
1355 npprint.print.embedPrint.window = window; |
|
1356 pi->Print(&npprint); |
|
1357 |
|
1358 ::CGContextTranslateCTM(cgContext, 0.0f, float(window.height)); |
|
1359 ::CGContextScaleCTM(cgContext, 1.0f, -1.0f); |
|
1360 CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer); |
|
1361 if (!image) { |
|
1362 ::CGContextRestoreGState(cgContext); |
|
1363 ::CGContextRelease(cgBuffer); |
|
1364 ::DisposeGWorld(gWorld); |
|
1365 nativeDraw.EndNativeDrawing(); |
|
1366 return; |
|
1367 } |
|
1368 ::CGContextDrawImage(cgContext, |
|
1369 ::CGRectMake(0, 0, window.width, window.height), |
|
1370 image); |
|
1371 ::CGImageRelease(image); |
|
1372 ::CGContextRelease(cgBuffer); |
|
1373 |
|
1374 ::DisposeGWorld(gWorld); |
|
1375 |
|
1376 nativeDraw.EndNativeDrawing(); |
|
1377 #pragma clang diagnostic warning "-Wdeprecated-declarations" |
|
1378 #elif defined(XP_UNIX) |
|
1379 |
|
1380 /* XXX this just flat-out doesn't work in a thebes world -- |
|
1381 * RenderEPS is a no-op. So don't bother to do any work here. |
|
1382 */ |
|
1383 (void)window; |
|
1384 (void)npprint; |
|
1385 |
|
1386 #elif defined(XP_WIN) |
|
1387 |
|
1388 /* On Windows, we use the win32 printing surface to print. This, in |
|
1389 * turn, uses the Cairo paginated surface, which in turn uses the |
|
1390 * meta surface to record all operations and then play them back. |
|
1391 * This doesn't work too well for plugins, because if plugins render |
|
1392 * directly into the DC, the meta surface won't have any knowledge |
|
1393 * of them, and so at the end when it actually does the replay step, |
|
1394 * it'll fill the background with white and draw over whatever was |
|
1395 * rendered before. |
|
1396 * |
|
1397 * So, to avoid this, we use PushGroup, which creates a new windows |
|
1398 * surface, the plugin renders to that, and then we use normal |
|
1399 * cairo methods to composite that in such that it's recorded using the |
|
1400 * meta surface. |
|
1401 */ |
|
1402 |
|
1403 /* we'll already be translated into the right spot by gfxWindowsNativeDrawing */ |
|
1404 nsSize contentSize = GetContentRectRelativeToSelf().Size(); |
|
1405 window.x = 0; |
|
1406 window.y = 0; |
|
1407 window.width = presContext->AppUnitsToDevPixels(contentSize.width); |
|
1408 window.height = presContext->AppUnitsToDevPixels(contentSize.height); |
|
1409 |
|
1410 gfxContext *ctx = aRenderingContext.ThebesContext(); |
|
1411 |
|
1412 ctx->Save(); |
|
1413 |
|
1414 /* Make sure plugins don't do any damage outside of where they're supposed to */ |
|
1415 ctx->NewPath(); |
|
1416 gfxRect r(window.x, window.y, window.width, window.height); |
|
1417 ctx->Rectangle(r); |
|
1418 ctx->Clip(); |
|
1419 |
|
1420 gfxWindowsNativeDrawing nativeDraw(ctx, r); |
|
1421 do { |
|
1422 HDC dc = nativeDraw.BeginNativeDrawing(); |
|
1423 if (!dc) |
|
1424 return; |
|
1425 |
|
1426 // XXX don't we need to call nativeDraw.TransformToNativeRect here? |
|
1427 npprint.print.embedPrint.platformPrint = dc; |
|
1428 npprint.print.embedPrint.window = window; |
|
1429 // send off print info to plugin |
|
1430 pi->Print(&npprint); |
|
1431 |
|
1432 nativeDraw.EndNativeDrawing(); |
|
1433 } while (nativeDraw.ShouldRenderAgain()); |
|
1434 nativeDraw.PaintToContext(); |
|
1435 |
|
1436 ctx->Restore(); |
|
1437 #endif |
|
1438 |
|
1439 // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same? |
|
1440 // XXX Calling DidReflow here makes no sense!!! |
|
1441 nsDidReflowStatus status = nsDidReflowStatus::FINISHED; // should we use a special status? |
|
1442 frame->DidReflow(presContext, |
|
1443 nullptr, status); // DidReflow will take care of it |
|
1444 } |
|
1445 |
|
1446 nsRect |
|
1447 nsObjectFrame::GetPaintedRect(nsDisplayPlugin* aItem) |
|
1448 { |
|
1449 if (!mInstanceOwner) |
|
1450 return nsRect(); |
|
1451 nsRect r = GetContentRectRelativeToSelf(); |
|
1452 if (!mInstanceOwner->UseAsyncRendering()) |
|
1453 return r; |
|
1454 |
|
1455 nsIntSize size = mInstanceOwner->GetCurrentImageSize(); |
|
1456 nsPresContext* pc = PresContext(); |
|
1457 r.IntersectRect(r, nsRect(0, 0, pc->DevPixelsToAppUnits(size.width), |
|
1458 pc->DevPixelsToAppUnits(size.height))); |
|
1459 return r; |
|
1460 } |
|
1461 |
|
1462 LayerState |
|
1463 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder, |
|
1464 LayerManager* aManager) |
|
1465 { |
|
1466 if (!mInstanceOwner) |
|
1467 return LAYER_NONE; |
|
1468 |
|
1469 #ifdef MOZ_WIDGET_ANDROID |
|
1470 // We always want a layer on Honeycomb and later |
|
1471 if (AndroidBridge::Bridge()->GetAPIVersion() >= 11) |
|
1472 return LAYER_ACTIVE; |
|
1473 #endif |
|
1474 |
|
1475 if (!mInstanceOwner->UseAsyncRendering()) { |
|
1476 return LAYER_NONE; |
|
1477 } |
|
1478 |
|
1479 return LAYER_ACTIVE; |
|
1480 } |
|
1481 |
|
1482 already_AddRefed<Layer> |
|
1483 nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder, |
|
1484 LayerManager* aManager, |
|
1485 nsDisplayItem* aItem, |
|
1486 const ContainerLayerParameters& aContainerParameters) |
|
1487 { |
|
1488 if (!mInstanceOwner) |
|
1489 return nullptr; |
|
1490 |
|
1491 NPWindow* window = nullptr; |
|
1492 mInstanceOwner->GetWindow(window); |
|
1493 if (!window) |
|
1494 return nullptr; |
|
1495 |
|
1496 if (window->width <= 0 || window->height <= 0) |
|
1497 return nullptr; |
|
1498 |
|
1499 // window is in "display pixels", but size needs to be in device pixels |
|
1500 double scaleFactor = 1.0; |
|
1501 if (NS_FAILED(mInstanceOwner->GetContentsScaleFactor(&scaleFactor))) { |
|
1502 scaleFactor = 1.0; |
|
1503 } |
|
1504 int intScaleFactor = ceil(scaleFactor); |
|
1505 IntSize size(window->width * intScaleFactor, window->height * intScaleFactor); |
|
1506 |
|
1507 nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame(); |
|
1508 gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel()); |
|
1509 // to provide crisper and faster drawing. |
|
1510 r.Round(); |
|
1511 nsRefPtr<Layer> layer = |
|
1512 (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem)); |
|
1513 |
|
1514 if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) { |
|
1515 // Create image |
|
1516 nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer(); |
|
1517 if (!container) { |
|
1518 // This can occur if our instance is gone. |
|
1519 return nullptr; |
|
1520 } |
|
1521 |
|
1522 if (!layer) { |
|
1523 mInstanceOwner->NotifyPaintWaiter(aBuilder); |
|
1524 // Initialize ImageLayer |
|
1525 layer = aManager->CreateImageLayer(); |
|
1526 if (!layer) |
|
1527 return nullptr; |
|
1528 } |
|
1529 |
|
1530 NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type"); |
|
1531 ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get()); |
|
1532 #ifdef XP_MACOSX |
|
1533 if (!mInstanceOwner->UseAsyncRendering()) { |
|
1534 mInstanceOwner->DoCocoaEventDrawRect(r, nullptr); |
|
1535 } |
|
1536 #endif |
|
1537 |
|
1538 imglayer->SetScaleToSize(size, ScaleMode::STRETCH); |
|
1539 imglayer->SetContainer(container); |
|
1540 GraphicsFilter filter = |
|
1541 nsLayoutUtils::GetGraphicsFilterForFrame(this); |
|
1542 #ifdef MOZ_GFX_OPTIMIZE_MOBILE |
|
1543 if (!aManager->IsCompositingCheap()) { |
|
1544 // Pixman just horrible with bilinear filter scaling |
|
1545 filter = GraphicsFilter::FILTER_NEAREST; |
|
1546 } |
|
1547 #endif |
|
1548 imglayer->SetFilter(filter); |
|
1549 |
|
1550 layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0); |
|
1551 #ifdef MOZ_WIDGET_ANDROID |
|
1552 } else if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_VIDEO) { |
|
1553 nsDisplayPluginVideo* videoItem = reinterpret_cast<nsDisplayPluginVideo*>(aItem); |
|
1554 nsNPAPIPluginInstance::VideoInfo* videoInfo = videoItem->VideoInfo(); |
|
1555 |
|
1556 nsRefPtr<ImageContainer> container = mInstanceOwner->GetImageContainerForVideo(videoInfo); |
|
1557 if (!container) |
|
1558 return nullptr; |
|
1559 |
|
1560 if (!layer) { |
|
1561 // Initialize ImageLayer |
|
1562 layer = aManager->CreateImageLayer(); |
|
1563 if (!layer) |
|
1564 return nullptr; |
|
1565 } |
|
1566 |
|
1567 ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get()); |
|
1568 imglayer->SetContainer(container); |
|
1569 |
|
1570 layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0); |
|
1571 |
|
1572 // Set the offset and size according to the video dimensions |
|
1573 r.MoveBy(videoInfo->mDimensions.TopLeft()); |
|
1574 size.width = videoInfo->mDimensions.width; |
|
1575 size.height = videoInfo->mDimensions.height; |
|
1576 #endif |
|
1577 } else { |
|
1578 NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK, |
|
1579 "Unknown item type"); |
|
1580 NS_ABORT_IF_FALSE(!IsOpaque(), "Opaque plugins don't use backgrounds"); |
|
1581 |
|
1582 if (!layer) { |
|
1583 layer = aManager->CreateReadbackLayer(); |
|
1584 if (!layer) |
|
1585 return nullptr; |
|
1586 } |
|
1587 NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type"); |
|
1588 |
|
1589 ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get()); |
|
1590 if (readback->GetSize() != ThebesIntSize(size)) { |
|
1591 // This will destroy any old background sink and notify us that the |
|
1592 // background is now unknown |
|
1593 readback->SetSink(nullptr); |
|
1594 readback->SetSize(ThebesIntSize(size)); |
|
1595 |
|
1596 if (mBackgroundSink) { |
|
1597 // Maybe we still have a background sink associated with another |
|
1598 // readback layer that wasn't recycled for some reason? Unhook it |
|
1599 // now so that if this frame goes away, it doesn't have a dangling |
|
1600 // reference to us. |
|
1601 mBackgroundSink->Destroy(); |
|
1602 } |
|
1603 mBackgroundSink = |
|
1604 new PluginBackgroundSink(this, |
|
1605 readback->AllocateSequenceNumber()); |
|
1606 readback->SetSink(mBackgroundSink); |
|
1607 // The layer has taken ownership of our sink. When either the sink dies |
|
1608 // or the frame dies, the connection from the surviving object is nulled out. |
|
1609 } |
|
1610 } |
|
1611 |
|
1612 // Set a transform on the layer to draw the plugin in the right place |
|
1613 Matrix transform; |
|
1614 gfxPoint p = r.TopLeft() + aContainerParameters.mOffset; |
|
1615 transform.Translate(p.x, p.y); |
|
1616 |
|
1617 layer->SetBaseTransform(Matrix4x4::From2D(transform)); |
|
1618 layer->SetVisibleRegion(ThebesIntRect(IntRect(IntPoint(0, 0), size))); |
|
1619 return layer.forget(); |
|
1620 } |
|
1621 |
|
1622 void |
|
1623 nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder, |
|
1624 nsRenderingContext& aRenderingContext, |
|
1625 const nsRect& aDirtyRect, const nsRect& aPluginRect) |
|
1626 { |
|
1627 #if defined(MOZ_WIDGET_ANDROID) |
|
1628 if (mInstanceOwner) { |
|
1629 gfxRect frameGfxRect = |
|
1630 PresContext()->AppUnitsToGfxUnits(aPluginRect); |
|
1631 gfxRect dirtyGfxRect = |
|
1632 PresContext()->AppUnitsToGfxUnits(aDirtyRect); |
|
1633 |
|
1634 gfxContext* ctx = aRenderingContext.ThebesContext(); |
|
1635 |
|
1636 mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect); |
|
1637 return; |
|
1638 } |
|
1639 #endif |
|
1640 |
|
1641 // Screen painting code |
|
1642 #if defined(XP_MACOSX) |
|
1643 // delegate all painting to the plugin instance. |
|
1644 if (mInstanceOwner) { |
|
1645 if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics || |
|
1646 mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation || |
|
1647 mInstanceOwner->GetDrawingModel() == |
|
1648 NPDrawingModelInvalidatingCoreAnimation) { |
|
1649 int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel(); |
|
1650 // Clip to the content area where the plugin should be drawn. If |
|
1651 // we don't do this, the plugin can draw outside its bounds. |
|
1652 nsIntRect contentPixels = aPluginRect.ToNearestPixels(appUnitsPerDevPixel); |
|
1653 nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel); |
|
1654 nsIntRect clipPixels; |
|
1655 clipPixels.IntersectRect(contentPixels, dirtyPixels); |
|
1656 |
|
1657 // Don't invoke the drawing code if the clip is empty. |
|
1658 if (clipPixels.IsEmpty()) |
|
1659 return; |
|
1660 |
|
1661 gfxRect nativeClipRect(clipPixels.x, clipPixels.y, |
|
1662 clipPixels.width, clipPixels.height); |
|
1663 gfxContext* ctx = aRenderingContext.ThebesContext(); |
|
1664 |
|
1665 gfxContextAutoSaveRestore save(ctx); |
|
1666 ctx->NewPath(); |
|
1667 ctx->Rectangle(nativeClipRect); |
|
1668 ctx->Clip(); |
|
1669 gfxPoint offset(contentPixels.x, contentPixels.y); |
|
1670 ctx->Translate(offset); |
|
1671 |
|
1672 gfxQuartzNativeDrawing nativeDrawing(ctx, nativeClipRect - offset); |
|
1673 |
|
1674 CGContextRef cgContext = nativeDrawing.BeginNativeDrawing(); |
|
1675 if (!cgContext) { |
|
1676 NS_WARNING("null CGContextRef during PaintPlugin"); |
|
1677 return; |
|
1678 } |
|
1679 |
|
1680 nsRefPtr<nsNPAPIPluginInstance> inst; |
|
1681 GetPluginInstance(getter_AddRefs(inst)); |
|
1682 if (!inst) { |
|
1683 NS_WARNING("null plugin instance during PaintPlugin"); |
|
1684 nativeDrawing.EndNativeDrawing(); |
|
1685 return; |
|
1686 } |
|
1687 NPWindow* window; |
|
1688 mInstanceOwner->GetWindow(window); |
|
1689 if (!window) { |
|
1690 NS_WARNING("null plugin window during PaintPlugin"); |
|
1691 nativeDrawing.EndNativeDrawing(); |
|
1692 return; |
|
1693 } |
|
1694 NP_CGContext* cgPluginPortCopy = |
|
1695 static_cast<NP_CGContext*>(mInstanceOwner->GetPluginPortCopy()); |
|
1696 if (!cgPluginPortCopy) { |
|
1697 NS_WARNING("null plugin port copy during PaintPlugin"); |
|
1698 nativeDrawing.EndNativeDrawing(); |
|
1699 return; |
|
1700 } |
|
1701 |
|
1702 mInstanceOwner->BeginCGPaint(); |
|
1703 if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation || |
|
1704 mInstanceOwner->GetDrawingModel() == |
|
1705 NPDrawingModelInvalidatingCoreAnimation) { |
|
1706 // CoreAnimation is updated, render the layer and perform a readback. |
|
1707 mInstanceOwner->RenderCoreAnimation(cgContext, window->width, window->height); |
|
1708 } else { |
|
1709 mInstanceOwner->Paint(nativeClipRect - offset, cgContext); |
|
1710 } |
|
1711 mInstanceOwner->EndCGPaint(); |
|
1712 |
|
1713 nativeDrawing.EndNativeDrawing(); |
|
1714 } else { |
|
1715 // FIXME - Bug 385435: Doesn't aDirtyRect need translating too? |
|
1716 nsRenderingContext::AutoPushTranslation |
|
1717 translate(&aRenderingContext, aPluginRect.TopLeft()); |
|
1718 |
|
1719 // this rect is used only in the CoreGraphics drawing model |
|
1720 gfxRect tmpRect(0, 0, 0, 0); |
|
1721 mInstanceOwner->Paint(tmpRect, nullptr); |
|
1722 } |
|
1723 } |
|
1724 #elif defined(MOZ_X11) |
|
1725 if (mInstanceOwner) { |
|
1726 NPWindow *window; |
|
1727 mInstanceOwner->GetWindow(window); |
|
1728 if (window->type == NPWindowTypeDrawable) { |
|
1729 gfxRect frameGfxRect = |
|
1730 PresContext()->AppUnitsToGfxUnits(aPluginRect); |
|
1731 gfxRect dirtyGfxRect = |
|
1732 PresContext()->AppUnitsToGfxUnits(aDirtyRect); |
|
1733 gfxContext* ctx = aRenderingContext.ThebesContext(); |
|
1734 |
|
1735 mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect); |
|
1736 } |
|
1737 } |
|
1738 #elif defined(XP_WIN) |
|
1739 nsRefPtr<nsNPAPIPluginInstance> inst; |
|
1740 GetPluginInstance(getter_AddRefs(inst)); |
|
1741 if (inst) { |
|
1742 gfxRect frameGfxRect = |
|
1743 PresContext()->AppUnitsToGfxUnits(aPluginRect); |
|
1744 gfxRect dirtyGfxRect = |
|
1745 PresContext()->AppUnitsToGfxUnits(aDirtyRect); |
|
1746 gfxContext *ctx = aRenderingContext.ThebesContext(); |
|
1747 gfxMatrix currentMatrix = ctx->CurrentMatrix(); |
|
1748 |
|
1749 if (ctx->UserToDevicePixelSnapped(frameGfxRect, false)) { |
|
1750 dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect); |
|
1751 ctx->IdentityMatrix(); |
|
1752 } |
|
1753 dirtyGfxRect.RoundOut(); |
|
1754 |
|
1755 // Look if it's windowless |
|
1756 NPWindow *window; |
|
1757 mInstanceOwner->GetWindow(window); |
|
1758 |
|
1759 if (window->type == NPWindowTypeDrawable) { |
|
1760 // the offset of the DC |
|
1761 nsPoint origin; |
|
1762 |
|
1763 gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect); |
|
1764 if (nativeDraw.IsDoublePass()) { |
|
1765 // OOP plugin specific: let the shim know before we paint if we are doing a |
|
1766 // double pass render. If this plugin isn't oop, the register window message |
|
1767 // will be ignored. |
|
1768 NPEvent pluginEvent; |
|
1769 pluginEvent.event = plugins::DoublePassRenderingEvent(); |
|
1770 pluginEvent.wParam = 0; |
|
1771 pluginEvent.lParam = 0; |
|
1772 if (pluginEvent.event) |
|
1773 inst->HandleEvent(&pluginEvent, nullptr); |
|
1774 } |
|
1775 do { |
|
1776 HDC hdc = nativeDraw.BeginNativeDrawing(); |
|
1777 if (!hdc) |
|
1778 return; |
|
1779 |
|
1780 RECT dest; |
|
1781 nativeDraw.TransformToNativeRect(frameGfxRect, dest); |
|
1782 RECT dirty; |
|
1783 nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty); |
|
1784 |
|
1785 window->window = hdc; |
|
1786 window->x = dest.left; |
|
1787 window->y = dest.top; |
|
1788 window->clipRect.left = 0; |
|
1789 window->clipRect.top = 0; |
|
1790 // if we're painting, we're visible. |
|
1791 window->clipRect.right = window->width; |
|
1792 window->clipRect.bottom = window->height; |
|
1793 |
|
1794 // Windowless plugins on windows need a special event to update their location, |
|
1795 // see bug 135737. |
|
1796 // |
|
1797 // bug 271442: note, the rectangle we send is now purely the bounds of the plugin |
|
1798 // relative to the window it is contained in, which is useful for the plugin to |
|
1799 // correctly translate mouse coordinates. |
|
1800 // |
|
1801 // this does not mesh with the comments for bug 135737 which imply that the rectangle |
|
1802 // must be clipped in some way to prevent the plugin attempting to paint over areas |
|
1803 // it shouldn't. |
|
1804 // |
|
1805 // since the two uses of the rectangle are mutually exclusive in some cases, and |
|
1806 // since I don't see any incorrect painting (at least with Flash and ViewPoint - |
|
1807 // the originator of bug 135737), it seems that windowless plugins are not relying |
|
1808 // on information here for clipping their drawing, and we can safely use this message |
|
1809 // to tell the plugin exactly where it is in all cases. |
|
1810 |
|
1811 nsIntPoint origin = GetWindowOriginInPixels(true); |
|
1812 nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height)); |
|
1813 |
|
1814 if (!mWindowlessRect.IsEqualEdges(winlessRect)) { |
|
1815 mWindowlessRect = winlessRect; |
|
1816 |
|
1817 WINDOWPOS winpos; |
|
1818 memset(&winpos, 0, sizeof(winpos)); |
|
1819 winpos.x = mWindowlessRect.x; |
|
1820 winpos.y = mWindowlessRect.y; |
|
1821 winpos.cx = mWindowlessRect.width; |
|
1822 winpos.cy = mWindowlessRect.height; |
|
1823 |
|
1824 // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event |
|
1825 NPEvent pluginEvent; |
|
1826 pluginEvent.event = WM_WINDOWPOSCHANGED; |
|
1827 pluginEvent.wParam = 0; |
|
1828 pluginEvent.lParam = (LPARAM)&winpos; |
|
1829 inst->HandleEvent(&pluginEvent, nullptr); |
|
1830 } |
|
1831 |
|
1832 inst->SetWindow(window); |
|
1833 |
|
1834 mInstanceOwner->Paint(dirty, hdc); |
|
1835 nativeDraw.EndNativeDrawing(); |
|
1836 } while (nativeDraw.ShouldRenderAgain()); |
|
1837 nativeDraw.PaintToContext(); |
|
1838 } |
|
1839 |
|
1840 ctx->SetMatrix(currentMatrix); |
|
1841 } |
|
1842 #endif |
|
1843 } |
|
1844 |
|
1845 nsresult |
|
1846 nsObjectFrame::HandleEvent(nsPresContext* aPresContext, |
|
1847 WidgetGUIEvent* anEvent, |
|
1848 nsEventStatus* anEventStatus) |
|
1849 { |
|
1850 NS_ENSURE_ARG_POINTER(anEvent); |
|
1851 NS_ENSURE_ARG_POINTER(anEventStatus); |
|
1852 nsresult rv = NS_OK; |
|
1853 |
|
1854 if (!mInstanceOwner) |
|
1855 return NS_ERROR_NULL_POINTER; |
|
1856 |
|
1857 mInstanceOwner->ConsiderNewEventloopNestingLevel(); |
|
1858 |
|
1859 if (anEvent->message == NS_PLUGIN_ACTIVATE) { |
|
1860 nsIFocusManager* fm = nsFocusManager::GetFocusManager(); |
|
1861 nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetContent()); |
|
1862 if (fm && elem) |
|
1863 return fm->SetFocus(elem, 0); |
|
1864 } |
|
1865 else if (anEvent->message == NS_PLUGIN_FOCUS) { |
|
1866 nsIFocusManager* fm = nsFocusManager::GetFocusManager(); |
|
1867 if (fm) |
|
1868 return fm->FocusPlugin(GetContent()); |
|
1869 } |
|
1870 |
|
1871 #ifdef XP_MACOSX |
|
1872 if (anEvent->message == NS_PLUGIN_RESOLUTION_CHANGED) { |
|
1873 double scaleFactor = 1.0; |
|
1874 mInstanceOwner->GetContentsScaleFactor(&scaleFactor); |
|
1875 mInstanceOwner->ContentsScaleFactorChanged(scaleFactor); |
|
1876 return NS_OK; |
|
1877 } |
|
1878 #endif |
|
1879 |
|
1880 if (mInstanceOwner->SendNativeEvents() && |
|
1881 anEvent->IsNativeEventDelivererForPlugin()) { |
|
1882 *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent); |
|
1883 // Due to plugin code reentering Gecko, this frame may be dead at this |
|
1884 // point. |
|
1885 return rv; |
|
1886 } |
|
1887 |
|
1888 #ifdef XP_WIN |
|
1889 rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus); |
|
1890 return rv; |
|
1891 #endif |
|
1892 |
|
1893 #ifdef XP_MACOSX |
|
1894 // we want to process some native mouse events in the cocoa event model |
|
1895 if ((anEvent->message == NS_MOUSE_ENTER || |
|
1896 anEvent->message == NS_WHEEL_WHEEL) && |
|
1897 mInstanceOwner->GetEventModel() == NPEventModelCocoa) { |
|
1898 *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent); |
|
1899 // Due to plugin code reentering Gecko, this frame may be dead at this |
|
1900 // point. |
|
1901 return rv; |
|
1902 } |
|
1903 |
|
1904 // These two calls to nsIPresShell::SetCapturingContext() (on mouse-down |
|
1905 // and mouse-up) are needed to make the routing of mouse events while |
|
1906 // dragging conform to standard OS X practice, and to the Cocoa NPAPI spec. |
|
1907 // See bug 525078 and bug 909678. |
|
1908 if (anEvent->message == NS_MOUSE_BUTTON_DOWN) { |
|
1909 nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED); |
|
1910 } |
|
1911 #endif |
|
1912 |
|
1913 rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus); |
|
1914 |
|
1915 // We need to be careful from this point because the call to |
|
1916 // nsObjectFrameSuper::HandleEvent() might have killed us. |
|
1917 |
|
1918 #ifdef XP_MACOSX |
|
1919 if (anEvent->message == NS_MOUSE_BUTTON_UP) { |
|
1920 nsIPresShell::SetCapturingContent(nullptr, 0); |
|
1921 } |
|
1922 #endif |
|
1923 |
|
1924 return rv; |
|
1925 } |
|
1926 |
|
1927 nsresult |
|
1928 nsObjectFrame::GetPluginInstance(nsNPAPIPluginInstance** aPluginInstance) |
|
1929 { |
|
1930 *aPluginInstance = nullptr; |
|
1931 |
|
1932 if (!mInstanceOwner) { |
|
1933 return NS_OK; |
|
1934 } |
|
1935 |
|
1936 return mInstanceOwner->GetInstance(aPluginInstance); |
|
1937 } |
|
1938 |
|
1939 nsresult |
|
1940 nsObjectFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor) |
|
1941 { |
|
1942 if (!mInstanceOwner) { |
|
1943 return NS_ERROR_FAILURE; |
|
1944 } |
|
1945 |
|
1946 nsRefPtr<nsNPAPIPluginInstance> inst; |
|
1947 mInstanceOwner->GetInstance(getter_AddRefs(inst)); |
|
1948 if (!inst) { |
|
1949 return NS_ERROR_FAILURE; |
|
1950 } |
|
1951 |
|
1952 bool useDOMCursor = static_cast<nsNPAPIPluginInstance*>(inst.get())->UsesDOMForCursor(); |
|
1953 if (!useDOMCursor) { |
|
1954 return NS_ERROR_FAILURE; |
|
1955 } |
|
1956 |
|
1957 return nsObjectFrameSuper::GetCursor(aPoint, aCursor); |
|
1958 } |
|
1959 |
|
1960 void |
|
1961 nsObjectFrame::SetIsDocumentActive(bool aIsActive) |
|
1962 { |
|
1963 #ifndef XP_MACOSX |
|
1964 if (mInstanceOwner) { |
|
1965 mInstanceOwner->UpdateDocumentActiveState(aIsActive); |
|
1966 } |
|
1967 #endif |
|
1968 } |
|
1969 |
|
1970 // static |
|
1971 nsIObjectFrame * |
|
1972 nsObjectFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot) |
|
1973 { |
|
1974 nsIFrame* child = aRoot->GetFirstPrincipalChild(); |
|
1975 |
|
1976 while (child) { |
|
1977 nsIObjectFrame* outFrame = do_QueryFrame(child); |
|
1978 if (outFrame) { |
|
1979 nsRefPtr<nsNPAPIPluginInstance> pi; |
|
1980 outFrame->GetPluginInstance(getter_AddRefs(pi)); // make sure we have a REAL plugin |
|
1981 if (pi) |
|
1982 return outFrame; |
|
1983 } |
|
1984 |
|
1985 outFrame = GetNextObjectFrame(aPresContext, child); |
|
1986 if (outFrame) |
|
1987 return outFrame; |
|
1988 child = child->GetNextSibling(); |
|
1989 } |
|
1990 |
|
1991 return nullptr; |
|
1992 } |
|
1993 |
|
1994 /*static*/ void |
|
1995 nsObjectFrame::BeginSwapDocShells(nsIContent* aContent, void*) |
|
1996 { |
|
1997 NS_PRECONDITION(aContent, ""); |
|
1998 |
|
1999 // This function is called from a document content enumerator so we need |
|
2000 // to filter out the nsObjectFrames and ignore the rest. |
|
2001 nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame()); |
|
2002 if (!obj) |
|
2003 return; |
|
2004 |
|
2005 nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj); |
|
2006 NS_ASSERTION(!objectFrame->mWidget || objectFrame->mWidget->GetParent(), |
|
2007 "Plugin windows must not be toplevel"); |
|
2008 objectFrame->UnregisterPluginForGeometryUpdates(); |
|
2009 } |
|
2010 |
|
2011 /*static*/ void |
|
2012 nsObjectFrame::EndSwapDocShells(nsIContent* aContent, void*) |
|
2013 { |
|
2014 NS_PRECONDITION(aContent, ""); |
|
2015 |
|
2016 // This function is called from a document content enumerator so we need |
|
2017 // to filter out the nsObjectFrames and ignore the rest. |
|
2018 nsIObjectFrame* obj = do_QueryFrame(aContent->GetPrimaryFrame()); |
|
2019 if (!obj) |
|
2020 return; |
|
2021 |
|
2022 nsObjectFrame* objectFrame = static_cast<nsObjectFrame*>(obj); |
|
2023 nsRootPresContext* rootPC = objectFrame->PresContext()->GetRootPresContext(); |
|
2024 NS_ASSERTION(rootPC, "unable to register the plugin frame"); |
|
2025 nsIWidget* widget = objectFrame->mWidget; |
|
2026 if (widget) { |
|
2027 // Reparent the widget. |
|
2028 nsIWidget* parent = |
|
2029 rootPC->PresShell()->GetRootFrame()->GetNearestWidget(); |
|
2030 widget->SetParent(parent); |
|
2031 nsWeakFrame weakFrame(objectFrame); |
|
2032 objectFrame->CallSetWindow(); |
|
2033 if (!weakFrame.IsAlive()) { |
|
2034 return; |
|
2035 } |
|
2036 } |
|
2037 |
|
2038 #ifdef XP_MACOSX |
|
2039 if (objectFrame->mWidget) { |
|
2040 objectFrame->RegisterPluginForGeometryUpdates(); |
|
2041 } |
|
2042 #else |
|
2043 objectFrame->RegisterPluginForGeometryUpdates(); |
|
2044 #endif |
|
2045 } |
|
2046 |
|
2047 nsIFrame* |
|
2048 NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) |
|
2049 { |
|
2050 return new (aPresShell) nsObjectFrame(aContext); |
|
2051 } |
|
2052 |
|
2053 bool |
|
2054 nsObjectFrame::IsPaintedByGecko() const |
|
2055 { |
|
2056 #ifdef XP_MACOSX |
|
2057 return true; |
|
2058 #else |
|
2059 return !mWidget; |
|
2060 #endif |
|
2061 } |
|
2062 |
|
2063 NS_IMPL_FRAMEARENA_HELPERS(nsObjectFrame) |