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 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Communicator client code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
24 * Pierre Phaneuf <pp@ludusdesign.com>
25 * Jacek Piskozub <piskozub@iopan.gda.pl>
26 * Leon Sha <leon.sha@sun.com>
27 * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
28 * Robert O'Callahan <roc+moz@cs.cmu.edu>
29 * Christian Biesinger <cbiesinger@web.de>
30 * Josh Aas <josh@mozilla.com>
31 * Mats Palmgren <matspal@gmail.com>
33 * Alternatively, the contents of this file may be used under the terms of
34 * either of the GNU General Public License Version 2 or later (the "GPL"),
35 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
36 * in which case the provisions of the GPL or the LGPL are applicable instead
37 * of those above. If you wish to allow use of your version of this file only
38 * under the terms of either the GPL or the LGPL, and not to allow others to
39 * use your version of this file under the terms of the MPL, indicate your
40 * decision by deleting the provisions above and replace them with the notice
41 * and other provisions required by the GPL or the LGPL. If you do not delete
42 * the provisions above, a recipient may use your version of this file under
43 * the terms of any one of the MPL, the GPL or the LGPL.
45 * ***** END LICENSE BLOCK ***** */
47 /* rendering objects for replaced elements implemented by a plugin */
59 #include "mozilla/plugins/PluginMessageUtils.h"
63 #include <cairo-xlib.h>
64 #include "gfxXlibSurface.h"
66 enum { XKeyPress
= KeyPress
};
74 #include "nsPresContext.h"
75 #include "nsIPresShell.h"
76 #include "nsWidgetsCID.h"
78 #include "nsIViewManager.h"
79 #include "nsIDOMKeyListener.h"
80 #include "nsIDOMDragEvent.h"
81 #include "nsIPluginHost.h"
83 #include "nsReadableUtils.h"
85 #include "nsGkAtoms.h"
86 #include "nsIAppShell.h"
87 #include "nsIDocument.h"
88 #include "nsINodeInfo.h"
90 #include "nsNetUtil.h"
91 #include "nsIPluginInstanceOwner.h"
92 #include "nsIPluginInstance.h"
93 #include "nsIPluginTagInfo.h"
95 #include "nsILinkHandler.h"
96 #include "nsIScrollPositionListener.h"
98 #include "nsIDocShellTreeItem.h"
99 #include "nsIDocShellTreeOwner.h"
100 #include "nsDocShellCID.h"
101 #include "nsIWebBrowserChrome.h"
102 #include "nsIDOMElement.h"
103 #include "nsIDOMNodeList.h"
104 #include "nsIDOMHTMLObjectElement.h"
105 #include "nsIDOMHTMLEmbedElement.h"
106 #include "nsIDOMHTMLAppletElement.h"
107 #include "nsIDOMWindow.h"
108 #include "nsIDOMDocumentEvent.h"
109 #include "nsIDOMMouseListener.h"
110 #include "nsIDOMMouseMotionListener.h"
111 #include "nsIDOMFocusListener.h"
112 #include "nsIDOMContextMenuListener.h"
113 #include "nsIDOMEventTarget.h"
114 #include "nsIDOMNSEvent.h"
115 #include "nsIPrivateDOMEvent.h"
116 #include "nsIDocumentEncoder.h"
117 #include "nsXPIDLString.h"
118 #include "nsIDOMRange.h"
119 #include "nsIPluginWidget.h"
120 #include "nsGUIEvent.h"
121 #include "nsIRenderingContext.h"
123 #include "nsTransform2D.h"
124 #include "nsIImageLoadingContent.h"
125 #include "nsIObjectLoadingContent.h"
126 #include "nsPIDOMWindow.h"
127 #include "nsIDOMElement.h"
128 #include "nsContentUtils.h"
129 #include "nsDisplayList.h"
130 #include "nsAttrName.h"
131 #include "nsDataHashtable.h"
132 #include "nsDOMClassInfo.h"
133 #include "nsFocusManager.h"
134 #include "nsLayoutUtils.h"
135 #include "nsFrameManager.h"
136 #include "nsComponentManagerUtils.h"
137 #include "nsIObserverService.h"
138 #include "nsIScrollableFrame.h"
140 // headers for plugin scriptability
141 #include "nsIScriptGlobalObject.h"
142 #include "nsIScriptContext.h"
143 #include "nsIXPConnect.h"
144 #include "nsIXPCScriptable.h"
145 #include "nsIClassInfo.h"
146 #include "nsIDOMClientRect.h"
148 #include "nsObjectFrame.h"
149 #include "nsIObjectFrame.h"
150 #include "nsPluginNativeWindow.h"
151 #include "nsIPluginDocument.h"
152 #include "FrameLayerBuilder.h"
154 #include "nsThreadUtils.h"
156 #include "gfxContext.h"
157 #include "gfxPlatform.h"
160 #include "gfxWindowsNativeDrawing.h"
161 #include "gfxWindowsSurface.h"
164 #include "gfxImageSurface.h"
165 #include "gfxUtils.h"
167 #include "ReadbackLayer.h"
169 // accessibility support
171 #include "nsAccessibilityService.h"
175 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
176 #endif /* MOZ_LOGGING */
181 #include "nsContentCID.h"
182 static NS_DEFINE_CID(kRangeCID
, NS_RANGE_CID
);
183 static NS_DEFINE_CID(kAppShellCID
, NS_APPSHELL_CID
);
186 #include "gfxQuartzNativeDrawing.h"
187 #include "nsPluginUtilsOSX.h"
188 #include "nsCoreAnimationSupport.h"
192 #if (MOZ_PLATFORM_MAEMO == 5) && defined(MOZ_WIDGET_GTK2)
193 #define MOZ_COMPOSITED_PLUGINS 1
194 #define MOZ_USE_IMAGE_EXPOSE 1
195 #include <X11/Xutil.h>
196 #include <X11/Xatom.h>
197 #include <X11/extensions/XShm.h>
202 #ifdef MOZ_WIDGET_GTK2
204 #include <gdk/gdkx.h>
206 #include "gfxXlibNativeRenderer.h"
211 #include "gfxQtNativeRenderer.h"
215 #include "mozilla/X11Util.h"
216 using mozilla::DefaultXDisplay
;
230 #ifdef CreateEvent // Thank you MS.
235 static PRLogModuleInfo
*nsObjectFrameLM
= PR_NewLogModule("nsObjectFrame");
236 #endif /* PR_LOGGING */
238 #if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
239 #define MAC_CARBON_PLUGINS
242 using namespace mozilla
;
244 using namespace mozilla::plugins
;
246 using namespace mozilla::layers
;
248 // special class for handeling DOM context menu events because for
249 // some reason it starves other mouse events if implemented on the
251 class nsPluginDOMContextMenuListener
: public nsIDOMContextMenuListener
254 nsPluginDOMContextMenuListener();
255 virtual ~nsPluginDOMContextMenuListener();
259 NS_IMETHOD
ContextMenu(nsIDOMEvent
* aContextMenuEvent
);
261 nsresult
Init(nsIContent
* aContent
);
262 nsresult
Destroy(nsIContent
* aContent
);
264 NS_IMETHOD
HandleEvent(nsIDOMEvent
* aEvent
)
268 nsEventStatus
ProcessEvent(const nsGUIEvent
& anEvent
)
270 return nsEventStatus_eConsumeNoDefault
;
275 class nsPluginInstanceOwner
: public nsIPluginInstanceOwner
,
276 public nsIPluginInstanceOwner_MOZILLA_2_0_BRANCH
,
277 public nsIPluginTagInfo
,
278 public nsIDOMMouseListener
,
279 public nsIDOMMouseMotionListener
,
280 public nsIDOMKeyListener
,
281 public nsIDOMFocusListener
,
282 public nsIScrollPositionListener
285 nsPluginInstanceOwner();
286 virtual ~nsPluginInstanceOwner();
290 //nsIPluginInstanceOwner interface
291 NS_DECL_NSIPLUGININSTANCEOWNER
292 NS_DECL_NSIPLUGININSTANCEOWNER_MOZILLA_2_0_BRANCH
294 NS_IMETHOD
GetURL(const char *aURL
, const char *aTarget
,
295 nsIInputStream
*aPostStream
,
296 void *aHeadersData
, PRUint32 aHeadersDataLen
);
298 NS_IMETHOD
ShowStatus(const PRUnichar
*aStatusMsg
);
300 NPError
ShowNativeContextMenu(NPMenu
* menu
, void* event
);
302 NPBool
ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
303 double *destX
, double *destY
, NPCoordinateSpace destSpace
);
305 //nsIPluginTagInfo interface
306 NS_DECL_NSIPLUGINTAGINFO
308 // nsIDOMMouseListener interfaces
309 NS_IMETHOD
MouseDown(nsIDOMEvent
* aMouseEvent
);
310 NS_IMETHOD
MouseUp(nsIDOMEvent
* aMouseEvent
);
311 NS_IMETHOD
MouseClick(nsIDOMEvent
* aMouseEvent
);
312 NS_IMETHOD
MouseDblClick(nsIDOMEvent
* aMouseEvent
);
313 NS_IMETHOD
MouseOver(nsIDOMEvent
* aMouseEvent
);
314 NS_IMETHOD
MouseOut(nsIDOMEvent
* aMouseEvent
);
315 NS_IMETHOD
HandleEvent(nsIDOMEvent
* aEvent
);
317 // nsIDOMMouseMotionListener interfaces
318 NS_IMETHOD
MouseMove(nsIDOMEvent
* aMouseEvent
);
319 NS_IMETHOD
DragMove(nsIDOMEvent
* aMouseEvent
) { return NS_OK
; }
321 // nsIDOMKeyListener interfaces
322 NS_IMETHOD
KeyDown(nsIDOMEvent
* aKeyEvent
);
323 NS_IMETHOD
KeyUp(nsIDOMEvent
* aKeyEvent
);
324 NS_IMETHOD
KeyPress(nsIDOMEvent
* aKeyEvent
);
326 // nsIDOMFocusListener interfaces
327 NS_IMETHOD
Focus(nsIDOMEvent
* aFocusEvent
);
328 NS_IMETHOD
Blur(nsIDOMEvent
* aFocusEvent
);
332 void PrepareToStop(PRBool aDelayedStop
);
335 void Paint(const RECT
& aDirty
, HDC aDC
);
336 #elif defined(XP_MACOSX)
337 void Paint(const gfxRect
& aDirtyRect
, CGContextRef cgContext
);
338 void RenderCoreAnimation(CGContextRef aCGContext
, int aWidth
, int aHeight
);
339 void DoCocoaEventDrawRect(const gfxRect
& aDrawRect
, CGContextRef cgContext
);
340 #elif defined(MOZ_X11)
341 void Paint(gfxContext
* aContext
,
342 const gfxRect
& aFrameRect
,
343 const gfxRect
& aDirtyRect
);
344 #elif defined(XP_OS2)
345 void Paint(const nsRect
& aDirtyRect
, HPS aHPS
);
348 #ifdef MAC_CARBON_PLUGINS
350 void StartTimer(PRBool isVisible
);
352 void SendIdleEvent();
354 // nsIScrollPositionListener interface
355 virtual void ScrollPositionWillChange(nscoord aX
, nscoord aY
);
356 virtual void ScrollPositionDidChange(nscoord aX
, nscoord aY
);
360 nsresult
Init(nsPresContext
* aPresContext
, nsObjectFrame
* aFrame
,
361 nsIContent
* aContent
);
363 void* GetPluginPortFromWidget();
364 void ReleasePluginPort(void* pluginPort
);
366 void SetPluginHost(nsIPluginHost
* aHost
);
368 nsEventStatus
ProcessEvent(const nsGUIEvent
& anEvent
);
371 NPDrawingModel
GetDrawingModel();
372 PRBool
IsRemoteDrawingCoreAnimation();
373 NPEventModel
GetEventModel();
374 static void CARefresh(nsITimer
*aTimer
, void *aClosure
);
375 static void AddToCARefreshTimer(nsPluginInstanceOwner
*aPluginInstance
);
376 static void RemoveFromCARefreshTimer(nsPluginInstanceOwner
*aPluginInstance
);
377 void SetupCARefresh();
378 void* FixUpPluginWindow(PRInt32 inPaintState
);
379 void HidePluginWindow();
380 // Set a flag that (if true) indicates the plugin port info has changed and
381 // SetWindow() needs to be called.
382 void SetPluginPortChanged(PRBool aState
) { mPluginPortChanged
= aState
; }
383 // Return a pointer to the internal nsPluginPort structure that's used to
384 // store a copy of plugin port info and to detect when it's been changed.
385 void* GetPluginPortCopy();
386 // Set plugin port info in the plugin (in the 'window' member of the
387 // NPWindow structure passed to the plugin by SetWindow()) and set a
388 // flag (mPluginPortChanged) to indicate whether or not this info has
389 // changed, and SetWindow() needs to be called again.
390 void* SetPluginPortAndDetectChange();
391 // Flag when we've set up a Thebes (and CoreGraphics) context in
392 // nsObjectFrame::PaintPlugin(). We need to know this in
393 // FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
394 // been called from nsObjectFrame::PaintPlugin() when we're using the
395 // CoreGraphics drawing model).
399 void UpdateWindowPositionAndClipRect(PRBool aSetWindow
);
400 void CallSetWindow();
401 void UpdateWindowVisibility(PRBool aVisible
);
404 void SetOwner(nsObjectFrame
*aOwner
)
406 mObjectFrame
= aOwner
;
409 PRUint32
GetLastEventloopNestingLevel() const {
410 return mLastEventloopNestingLevel
;
413 static PRUint32
GetEventloopNestingLevel();
415 void ConsiderNewEventloopNestingLevel() {
416 PRUint32 currentLevel
= GetEventloopNestingLevel();
418 if (currentLevel
< mLastEventloopNestingLevel
) {
419 mLastEventloopNestingLevel
= currentLevel
;
423 const char* GetPluginName()
425 if (mInstance
&& mPluginHost
) {
426 const char* name
= NULL
;
427 if (NS_SUCCEEDED(mPluginHost
->GetPluginName(mInstance
, &name
)) && name
)
434 void GetPluginDescription(nsACString
& aDescription
)
436 aDescription
.Truncate();
437 if (mInstance
&& mPluginHost
) {
438 nsCOMPtr
<nsIPluginTag
> pluginTag
;
439 mPluginHost
->GetPluginTagForInstance(mInstance
,
440 getter_AddRefs(pluginTag
));
442 pluginTag
->GetDescription(aDescription
);
448 PRBool
SendNativeEvents()
451 return mPluginWindow
->type
== NPWindowTypeDrawable
&&
452 MatchPluginName("Shockwave Flash");
453 #elif defined(MOZ_X11) || defined(XP_MACOSX)
460 PRBool
MatchPluginName(const char *aPluginName
)
462 return strncmp(GetPluginName(), aPluginName
, strlen(aPluginName
)) == 0;
465 #ifdef MOZ_USE_IMAGE_EXPOSE
466 nsresult
SetAbsoluteScreenPosition(nsIDOMElement
* element
,
467 nsIDOMClientRect
* position
,
468 nsIDOMClientRect
* clip
);
471 void NotifyPaintWaiter(nsDisplayListBuilder
* aBuilder
);
472 // Return true if we set image with valid surface
473 PRBool
SetCurrentImage(ImageContainer
* aContainer
);
475 // Methods to update the background image we send to async plugins.
476 // The eventual target of these operations is PluginInstanceParent,
477 // but it takes several hops to get there.
478 void SetBackgroundUnknown();
479 already_AddRefed
<gfxContext
> BeginUpdateBackground(const nsIntRect
& aRect
);
480 void EndUpdateBackground(gfxContext
* aContext
, const nsIntRect
& aRect
);
482 PRBool
UseAsyncRendering()
484 PRBool useAsyncRendering
;
486 NS_SUCCEEDED(mInstance
->UseAsyncPainting(&useAsyncRendering
)) &&
489 mPluginWindow
->type
== NPWindowTypeDrawable
));
494 // return FALSE if LayerSurface dirty (newly created and don't have valid plugin content yet)
497 nsRefPtr
<ImageContainer
> container
= mObjectFrame
->GetImageContainer();
502 nsCOMPtr
<nsIPluginInstance_MOZILLA_2_0_BRANCH
> inst
= do_QueryInterface(mInstance
);
507 nsRefPtr
<Image
> image
;
508 if (!NS_SUCCEEDED(inst
->GetImage(container
, getter_AddRefs(image
))) || !image
)
511 container
->SetCurrentImage(image
);
513 if (container
->GetCurrentSize() != gfxIntSize(mPluginWindow
->width
, mPluginWindow
->height
))
518 already_AddRefed
<nsIPluginInstance_MOZILLA_2_0_BRANCH
>
521 nsCOMPtr
<nsIPluginInstance_MOZILLA_2_0_BRANCH
> inst
= do_QueryInterface(mInstance
);
522 return inst
.forget();
525 void FixUpURLS(const nsString
&name
, nsAString
&value
);
527 nsPluginNativeWindow
*mPluginWindow
;
528 nsCOMPtr
<nsIPluginInstance
> mInstance
;
529 nsObjectFrame
*mObjectFrame
; // owns nsPluginInstanceOwner
530 nsCOMPtr
<nsIContent
> mContent
;
531 nsCString mDocumentBase
;
533 nsCOMPtr
<nsIWidget
> mWidget
;
534 nsCOMPtr
<nsIPluginHost
> mPluginHost
;
537 NP_CGContext mCGPluginPortCopy
;
538 #ifndef NP_NO_QUICKDRAW
539 NP_Port mQDPluginPortCopy
;
541 PRInt32 mInCGPaintLevel
;
542 nsIOSurface
*mIOSurface
;
543 nsCARenderer mCARenderer
;
544 static nsCOMPtr
<nsITimer
> *sCATimer
;
545 static nsTArray
<nsPluginInstanceOwner
*> *sCARefreshListeners
;
546 PRBool mSentInitialTopLevelWindowEvent
;
549 // Initially, the event loop nesting level we were created on, it's updated
550 // if we detect the appshell is on a lower level as long as we're not stopped.
551 // We delay DoStopPlugin() until the appshell reaches this level or lower.
552 PRUint32 mLastEventloopNestingLevel
;
553 PRPackedBool mContentFocused
;
554 PRPackedBool mWidgetVisible
; // used on Mac to store our widget's visible state
556 PRPackedBool mPluginPortChanged
;
559 // Used with windowless plugins only, initialized in CreateWidget().
560 PRPackedBool mFlash10Quirks
;
562 PRPackedBool mPluginWindowVisible
;
564 // If true, destroy the widget on destruction. Used when plugin stop
565 // is being delayed to a safer point in time.
566 PRPackedBool mDestroyWidget
;
567 PRUint16 mNumCachedAttrs
;
568 PRUint16 mNumCachedParams
;
569 char **mCachedAttrParamNames
;
570 char **mCachedAttrParamValues
;
572 #ifdef MOZ_COMPOSITED_PLUGINS
573 nsIntPoint mLastPoint
;
577 NPEventModel mEventModel
;
580 // pointer to wrapper for nsIDOMContextMenuListener
581 nsRefPtr
<nsPluginDOMContextMenuListener
> mCXMenuListener
;
583 nsresult
DispatchKeyToPlugin(nsIDOMEvent
* aKeyEvent
);
584 nsresult
DispatchMouseToPlugin(nsIDOMEvent
* aMouseEvent
);
585 nsresult
DispatchFocusToPlugin(nsIDOMEvent
* aFocusEvent
);
587 nsresult
EnsureCachedAttrParamArrays();
589 #ifdef MOZ_COMPOSITED_PLUGINS
590 nsEventStatus
ProcessEventX11Composited(const nsGUIEvent
& anEvent
);
595 #if defined(MOZ_WIDGET_GTK2)
596 : public gfxXlibNativeRenderer
597 #elif defined(MOZ_WIDGET_QT)
598 : public gfxQtNativeRenderer
602 Renderer(NPWindow
* aWindow
, nsPluginInstanceOwner
* aInstanceOwner
,
603 const nsIntSize
& aPluginSize
, const nsIntRect
& aDirtyRect
)
604 : mWindow(aWindow
), mInstanceOwner(aInstanceOwner
),
605 mPluginSize(aPluginSize
), mDirtyRect(aDirtyRect
)
607 virtual nsresult
DrawWithXlib(gfxXlibSurface
* surface
, nsIntPoint offset
,
608 nsIntRect
* clipRects
, PRUint32 numClipRects
);
611 nsPluginInstanceOwner
* mInstanceOwner
;
612 const nsIntSize
& mPluginSize
;
613 const nsIntRect
& mDirtyRect
;
617 #ifdef MOZ_USE_IMAGE_EXPOSE
619 // On hildon, we attempt to use NPImageExpose which allows us faster
622 // used to keep track of how big our buffer is.
623 nsIntSize mPluginSize
;
625 // The absolute position on the screen to draw to.
626 gfxRect mAbsolutePosition
;
628 // The clip region that we should draw into.
629 gfxRect mAbsolutePositionClip
;
633 XImage
*mSharedXImage
;
634 XShmSegmentInfo mSharedSegmentInfo
;
638 void NativeImageDraw(NPRect
* invalidRect
= nsnull
);
639 PRBool
UpdateVisibility(PRBool aVisible
);
643 PRPackedBool mWaitingForPaint
;
646 class PluginBackgroundSink
: public ReadbackSink
{
648 PluginBackgroundSink(nsObjectFrame
* aFrame
, PRUint64 aStartSequenceNumber
)
649 : mLastSequenceNumber(aStartSequenceNumber
), mFrame(aFrame
) {}
650 ~PluginBackgroundSink()
653 mFrame
->mBackgroundSink
= nsnull
;
657 virtual void SetUnknown(PRUint64 aSequenceNumber
)
659 if (!AcceptUpdate(aSequenceNumber
))
661 mFrame
->mInstanceOwner
->SetBackgroundUnknown();
664 virtual already_AddRefed
<gfxContext
>
665 BeginUpdate(const nsIntRect
& aRect
, PRUint64 aSequenceNumber
)
667 if (!AcceptUpdate(aSequenceNumber
))
669 return mFrame
->mInstanceOwner
->BeginUpdateBackground(aRect
);
672 virtual void EndUpdate(gfxContext
* aContext
, const nsIntRect
& aRect
)
674 return mFrame
->mInstanceOwner
->EndUpdateBackground(aContext
, aRect
);
677 void Destroy() { mFrame
= nsnull
; }
680 PRBool
AcceptUpdate(PRUint64 aSequenceNumber
) {
681 if (aSequenceNumber
> mLastSequenceNumber
&& mFrame
&&
682 mFrame
->mInstanceOwner
) {
683 mLastSequenceNumber
= aSequenceNumber
;
689 PRUint64 mLastSequenceNumber
;
690 nsObjectFrame
* mFrame
;
693 // Mac specific code to fix up port position and clip
696 enum { ePluginPaintEnable
, ePluginPaintDisable
};
700 nsObjectFrame::nsObjectFrame(nsStyleContext
* aContext
)
701 : nsObjectFrameSuper(aContext
)
702 , mReflowCallbackPosted(PR_FALSE
)
704 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
705 ("Created new nsObjectFrame %p\n", this));
708 nsObjectFrame::~nsObjectFrame()
710 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
711 ("nsObjectFrame %p deleted\n", this));
714 NS_QUERYFRAME_HEAD(nsObjectFrame
)
715 NS_QUERYFRAME_ENTRY(nsIObjectFrame
)
716 NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper
)
719 already_AddRefed
<nsAccessible
>
720 nsObjectFrame::CreateAccessible()
722 nsAccessibilityService
* accService
= nsIPresShell::AccService();
724 accService
->CreateHTMLObjectFrameAccessible(this, mContent
,
725 PresContext()->PresShell()) :
730 NS_IMETHODIMP
nsObjectFrame::GetPluginPort(HWND
*aPort
)
732 *aPort
= (HWND
) mInstanceOwner
->GetPluginPortFromWidget();
738 static NS_DEFINE_CID(kWidgetCID
, NS_CHILD_CID
);
741 nsObjectFrame::Init(nsIContent
* aContent
,
743 nsIFrame
* aPrevInFlow
)
745 NS_PRECONDITION(aContent
, "How did that happen?");
746 mPreventInstantiation
=
747 (aContent
->GetCurrentDoc()->GetDisplayDocument() != nsnull
);
749 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
750 ("Initializing nsObjectFrame %p for content %p\n", this, aContent
));
752 nsresult rv
= nsObjectFrameSuper::Init(aContent
, aParent
, aPrevInFlow
);
758 nsObjectFrame::DestroyFrom(nsIFrame
* aDestructRoot
)
760 NS_ASSERTION(!mPreventInstantiation
||
761 (mContent
&& mContent
->GetCurrentDoc()->GetDisplayDocument()),
762 "about to crash due to bug 136927");
764 // we need to finish with the plugin before native window is destroyed
765 // doing this in the destructor is too late.
766 StopPluginInternal(PR_TRUE
);
768 // StopPluginInternal might have disowned the widget; if it has,
769 // mWidget will be null.
771 mInnerView
->DetachWidgetEventHandler(mWidget
);
775 if (mBackgroundSink
) {
776 mBackgroundSink
->Destroy();
779 nsObjectFrameSuper::DestroyFrom(aDestructRoot
);
783 nsObjectFrame::DidSetStyleContext(nsStyleContext
* aOldStyleContext
)
786 nsIView
* view
= GetView();
787 nsIViewManager
* vm
= view
->GetViewManager();
789 nsViewVisibility visibility
=
790 IsHidden() ? nsViewVisibility_kHide
: nsViewVisibility_kShow
;
791 vm
->SetViewVisibility(view
, visibility
);
795 nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext
);
799 nsObjectFrame::GetType() const
801 return nsGkAtoms::objectFrame
;
806 nsObjectFrame::GetFrameName(nsAString
& aResult
) const
808 return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult
);
813 nsObjectFrame::CreateWidget(nscoord aWidth
,
817 nsIView
* view
= GetView();
818 NS_ASSERTION(view
, "Object frames must have views");
820 return NS_OK
; //XXX why OK? MMP
823 PRBool needsWidget
= !aViewOnly
;
824 PRBool canCreateWidget
= !nsIWidget::UsePuppetWidgets();
825 if (needsWidget
&& !canCreateWidget
) {
826 NS_WARNING("Can't use native widgets, and can't hand a plugins a PuppetWidget");
829 nsIViewManager
* viewMan
= view
->GetViewManager();
830 // mark the view as hidden since we don't know the (x,y) until Paint
831 // XXX is the above comment correct?
832 viewMan
->SetViewVisibility(view
, nsViewVisibility_kHide
);
834 nsCOMPtr
<nsIDeviceContext
> dx
;
835 viewMan
->GetDeviceContext(*getter_AddRefs(dx
));
837 //this is ugly. it was ripped off from didreflow(). MMP
838 // Position and size view relative to its parent, not relative to our
839 // parent frame (our parent frame may not have a view).
841 nsIView
* parentWithView
;
843 nsRect
r(0, 0, mRect
.width
, mRect
.height
);
845 GetOffsetFromView(origin
, &parentWithView
);
846 viewMan
->ResizeView(view
, r
);
847 viewMan
->MoveViewTo(view
, origin
.x
, origin
.y
);
849 nsRootPresContext
* rpc
= PresContext()->GetRootPresContext();
851 return NS_ERROR_FAILURE
;
854 if (needsWidget
&& !mWidget
&& canCreateWidget
) {
855 // XXX this breaks plugins in popups ... do we care?
856 nsIWidget
* parentWidget
=
857 rpc
->PresShell()->FrameManager()->GetRootFrame()->GetNearestWidget();
859 return NS_ERROR_FAILURE
;
861 mInnerView
= viewMan
->CreateView(GetContentRect() - GetPosition(), view
);
863 NS_ERROR("Could not create inner view");
864 return NS_ERROR_OUT_OF_MEMORY
;
866 viewMan
->InsertChild(view
, mInnerView
, nsnull
, PR_TRUE
);
869 mWidget
= do_CreateInstance(kWidgetCID
, &rv
);
873 nsWidgetInitData initData
;
874 initData
.mWindowType
= eWindowType_plugin
;
875 initData
.mUnicode
= PR_FALSE
;
876 initData
.clipChildren
= PR_TRUE
;
877 initData
.clipSiblings
= PR_TRUE
;
878 // We want mWidget to be able to deliver events to us, especially on
879 // Mac where events to the plugin are routed through Gecko. So we
880 // allow the view to attach its event handler to mWidget even though
881 // mWidget isn't the view's designated widget.
882 EVENT_CALLBACK eventHandler
= mInnerView
->AttachWidgetEventHandler(mWidget
);
883 rv
= mWidget
->Create(parentWidget
, nsnull
, nsIntRect(0,0,0,0),
884 eventHandler
, dx
, nsnull
, nsnull
, &initData
);
891 mWidget
->EnableDragDrop(PR_TRUE
);
893 // If this frame has an ancestor with a widget which is not
894 // the root prescontext's widget, then this plugin should not be
895 // displayed, so don't show the widget. If we show the widget, the
896 // plugin may appear in the main window. In Web content this would
897 // only happen with a plugin in a XUL popup.
898 if (parentWidget
== GetNearestWidget()) {
899 mWidget
->Show(PR_TRUE
);
901 // On Mac, we need to invalidate ourselves since even windowed
902 // plugins are painted through Thebes and we need to ensure
903 // the Thebes layer containing the plugin is updated.
904 Invalidate(GetContentRect() - GetPosition());
910 rpc
->RegisterPluginForGeometryUpdates(this);
911 rpc
->RequestUpdatePluginGeometry(this);
913 // Here we set the background color for this widget because some plugins will use
914 // the child window background color when painting. If it's not set, it may default to gray
915 // Sometimes, a frame doesn't have a background color or is transparent. In this
916 // case, walk up the frame tree until we do find a frame with a background color
917 for (nsIFrame
* frame
= this; frame
; frame
= frame
->GetParent()) {
919 frame
->GetVisitedDependentColor(eCSSProperty_background_color
);
920 if (NS_GET_A(bgcolor
) > 0) { // make sure we got an actual color
921 mWidget
->SetBackgroundColor(bgcolor
);
927 // Now that we have a widget we want to set the event model before
928 // any events are processed.
929 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
931 return NS_ERROR_FAILURE
;
932 pluginWidget
->SetPluginEventModel(mInstanceOwner
->GetEventModel());
933 pluginWidget
->SetPluginDrawingModel(mInstanceOwner
->GetDrawingModel());
935 if (mInstanceOwner
->GetDrawingModel() == NPDrawingModelCoreAnimation
) {
936 mInstanceOwner
->SetupCARefresh();
941 rpc
->RegisterPluginForGeometryUpdates(this);
946 viewMan
->SetViewVisibility(view
, nsViewVisibility_kShow
);
949 return (needsWidget
&& !canCreateWidget
) ? NS_ERROR_NOT_AVAILABLE
: NS_OK
;
952 #define EMBED_DEF_WIDTH 240
953 #define EMBED_DEF_HEIGHT 200
955 /* virtual */ nscoord
956 nsObjectFrame::GetMinWidth(nsIRenderingContext
*aRenderingContext
)
960 if (!IsHidden(PR_FALSE
)) {
961 nsIAtom
*atom
= mContent
->Tag();
962 if (atom
== nsGkAtoms::applet
|| atom
== nsGkAtoms::embed
) {
963 result
= nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH
);
967 DISPLAY_MIN_WIDTH(this, result
);
971 /* virtual */ nscoord
972 nsObjectFrame::GetPrefWidth(nsIRenderingContext
*aRenderingContext
)
974 return nsObjectFrame::GetMinWidth(aRenderingContext
);
978 nsObjectFrame::GetDesiredSize(nsPresContext
* aPresContext
,
979 const nsHTMLReflowState
& aReflowState
,
980 nsHTMLReflowMetrics
& aMetrics
)
982 // By default, we have no area
986 if (IsHidden(PR_FALSE
)) {
990 aMetrics
.width
= aReflowState
.ComputedWidth();
991 aMetrics
.height
= aReflowState
.ComputedHeight();
993 // for EMBED and APPLET, default to 240x200 for compatibility
994 nsIAtom
*atom
= mContent
->Tag();
995 if (atom
== nsGkAtoms::applet
|| atom
== nsGkAtoms::embed
) {
996 if (aMetrics
.width
== NS_UNCONSTRAINEDSIZE
) {
997 aMetrics
.width
= NS_MIN(NS_MAX(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH
),
998 aReflowState
.mComputedMinWidth
),
999 aReflowState
.mComputedMaxWidth
);
1001 if (aMetrics
.height
== NS_UNCONSTRAINEDSIZE
) {
1002 aMetrics
.height
= NS_MIN(NS_MAX(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT
),
1003 aReflowState
.mComputedMinHeight
),
1004 aReflowState
.mComputedMaxHeight
);
1007 #if defined (MOZ_WIDGET_GTK2)
1008 // We need to make sure that the size of the object frame does not
1009 // exceed the maximum size of X coordinates. See bug #225357 for
1010 // more information. In theory Gtk2 can handle large coordinates,
1011 // but underlying plugins can't.
1012 aMetrics
.height
= NS_MIN(aPresContext
->DevPixelsToAppUnits(PR_INT16_MAX
), aMetrics
.height
);
1013 aMetrics
.width
= NS_MIN(aPresContext
->DevPixelsToAppUnits(PR_INT16_MAX
), aMetrics
.width
);
1017 // At this point, the width has an unconstrained value only if we have
1018 // nothing to go on (no width set, no information from the plugin, nothing).
1019 // Make up a number.
1020 if (aMetrics
.width
== NS_UNCONSTRAINEDSIZE
) {
1022 (aReflowState
.mComputedMinWidth
!= NS_UNCONSTRAINEDSIZE
) ?
1023 aReflowState
.mComputedMinWidth
: 0;
1026 // At this point, the height has an unconstrained value only in two cases:
1027 // a) We are in standards mode with percent heights and parent is auto-height
1028 // b) We have no height information at all.
1029 // In either case, we have to make up a number.
1030 if (aMetrics
.height
== NS_UNCONSTRAINEDSIZE
) {
1032 (aReflowState
.mComputedMinHeight
!= NS_UNCONSTRAINEDSIZE
) ?
1033 aReflowState
.mComputedMinHeight
: 0;
1036 // XXXbz don't add in the border and padding, because we screw up our
1037 // plugin's size and positioning if we do... Eventually we _do_ want to
1038 // paint borders, though! At that point, we will need to adjust the desired
1039 // size either here or in Reflow.... Further, we will need to fix Paint() to
1040 // call the superclass in all cases.
1044 nsObjectFrame::Reflow(nsPresContext
* aPresContext
,
1045 nsHTMLReflowMetrics
& aMetrics
,
1046 const nsHTMLReflowState
& aReflowState
,
1047 nsReflowStatus
& aStatus
)
1049 DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
1050 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aMetrics
, aStatus
);
1052 // Get our desired size
1053 GetDesiredSize(aPresContext
, aReflowState
, aMetrics
);
1054 aMetrics
.SetOverflowAreasToDesiredBounds();
1055 FinishAndStoreOverflow(&aMetrics
);
1057 // delay plugin instantiation until all children have
1058 // arrived. Otherwise there may be PARAMs or other stuff that the
1059 // plugin needs to see that haven't arrived yet.
1060 if (!GetContent()->IsDoneAddingChildren()) {
1061 aStatus
= NS_FRAME_COMPLETE
;
1065 // if we are printing or print previewing, bail for now
1066 if (aPresContext
->Medium() == nsGkAtoms::print
) {
1067 aStatus
= NS_FRAME_COMPLETE
;
1071 nsRect
r(0, 0, aMetrics
.width
, aMetrics
.height
);
1072 r
.Deflate(aReflowState
.mComputedBorderPadding
);
1075 nsIViewManager
* vm
= mInnerView
->GetViewManager();
1076 vm
->MoveViewTo(mInnerView
, r
.x
, r
.y
);
1077 vm
->ResizeView(mInnerView
, nsRect(nsPoint(0, 0), r
.Size()), PR_TRUE
);
1080 FixupWindow(r
.Size());
1081 if (!mReflowCallbackPosted
) {
1082 mReflowCallbackPosted
= PR_TRUE
;
1083 aPresContext
->PresShell()->PostReflowCallback(this);
1086 aStatus
= NS_FRAME_COMPLETE
;
1088 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aMetrics
);
1092 ///////////// nsIReflowCallback ///////////////
1095 nsObjectFrame::ReflowFinished()
1097 mReflowCallbackPosted
= PR_FALSE
;
1103 nsObjectFrame::ReflowCallbackCanceled()
1105 mReflowCallbackPosted
= PR_FALSE
;
1109 nsObjectFrame::InstantiatePlugin(nsIPluginHost
* aPluginHost
,
1110 const char* aMimeType
,
1113 NS_ASSERTION(mPreventInstantiation
,
1114 "Instantiation should be prevented here!");
1116 // If you add early return(s), be sure to balance this call to
1117 // appShell->SuspendNative() with additional call(s) to
1118 // appShell->ReturnNative().
1119 nsCOMPtr
<nsIAppShell
> appShell
= do_GetService(kAppShellCID
);
1121 appShell
->SuspendNative();
1124 NS_ASSERTION(mContent
, "We should have a content node.");
1126 nsIDocument
* doc
= mContent
->GetOwnerDoc();
1127 nsCOMPtr
<nsIPluginDocument
> pDoc (do_QueryInterface(doc
));
1128 PRBool fullPageMode
= PR_FALSE
;
1130 pDoc
->GetWillHandleInstantiation(&fullPageMode
);
1134 if (fullPageMode
) { /* full-page mode */
1135 nsCOMPtr
<nsIStreamListener
> stream
;
1136 rv
= aPluginHost
->InstantiateFullPagePlugin(aMimeType
, aURI
, mInstanceOwner
, getter_AddRefs(stream
));
1137 if (NS_SUCCEEDED(rv
))
1138 pDoc
->SetStreamListener(stream
);
1139 } else { /* embedded mode */
1140 rv
= aPluginHost
->InstantiateEmbeddedPlugin(aMimeType
, aURI
,
1144 // Note that |this| may very well be destroyed already!
1147 appShell
->ResumeNative();
1154 nsObjectFrame::FixupWindow(const nsSize
& aSize
)
1156 nsPresContext
* presContext
= PresContext();
1158 if (!mInstanceOwner
)
1162 mInstanceOwner
->GetWindow(window
);
1164 NS_ENSURE_TRUE(window
, /**/);
1167 mInstanceOwner
->FixUpPluginWindow(ePluginPaintDisable
);
1170 PRBool windowless
= (window
->type
== NPWindowTypeDrawable
);
1172 nsIntPoint origin
= GetWindowOriginInPixels(windowless
);
1174 window
->x
= origin
.x
;
1175 window
->y
= origin
.y
;
1177 window
->width
= presContext
->AppUnitsToDevPixels(aSize
.width
);
1178 window
->height
= presContext
->AppUnitsToDevPixels(aSize
.height
);
1180 // on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
1181 // us from drawing on screen until the widget is properly positioned, which will not
1182 // happen until we have finished the reflow process.
1184 window
->clipRect
.top
= 0;
1185 window
->clipRect
.left
= 0;
1186 window
->clipRect
.bottom
= 0;
1187 window
->clipRect
.right
= 0;
1189 mInstanceOwner
->UpdateWindowPositionAndClipRect(PR_FALSE
);
1192 NotifyPluginReflowObservers();
1196 nsObjectFrame::CallSetWindow(PRBool aCheckIsHidden
)
1198 NPWindow
*win
= nsnull
;
1200 nsresult rv
= NS_ERROR_FAILURE
;
1201 nsCOMPtr
<nsIPluginInstance
> pi
;
1202 if (!mInstanceOwner
||
1203 NS_FAILED(rv
= mInstanceOwner
->GetInstance(*getter_AddRefs(pi
))) ||
1205 NS_FAILED(rv
= mInstanceOwner
->GetWindow(win
)) ||
1209 nsPluginNativeWindow
*window
= (nsPluginNativeWindow
*)win
;
1211 mInstanceOwner
->FixUpPluginWindow(ePluginPaintDisable
);
1214 if (aCheckIsHidden
&& IsHidden())
1215 return NS_ERROR_FAILURE
;
1217 // refresh the plugin port as well
1218 window
->window
= mInstanceOwner
->GetPluginPortFromWidget();
1220 // Adjust plugin dimensions according to pixel snap results
1221 // and reduce amount of SetWindow calls
1222 nsPresContext
* presContext
= PresContext();
1223 nsRootPresContext
* rootPC
= presContext
->GetRootPresContext();
1225 return NS_ERROR_FAILURE
;
1226 PRInt32 appUnitsPerDevPixel
= presContext
->AppUnitsPerDevPixel();
1227 nsIFrame
* rootFrame
= rootPC
->PresShell()->FrameManager()->GetRootFrame();
1228 nsRect bounds
= GetContentRect() + GetParent()->GetOffsetToCrossDoc(rootFrame
);
1229 nsIntRect intBounds
= bounds
.ToNearestPixels(appUnitsPerDevPixel
);
1230 window
->x
= intBounds
.x
;
1231 window
->y
= intBounds
.y
;
1232 window
->width
= intBounds
.width
;
1233 window
->height
= intBounds
.height
;
1235 // this will call pi->SetWindow and take care of window subclassing
1236 // if needed, see bug 132759.
1237 if (mInstanceOwner
->UseAsyncRendering()) {
1238 rv
= pi
->AsyncSetWindow(window
);
1241 rv
= window
->CallSetWindow(pi
);
1244 mInstanceOwner
->ReleasePluginPort(window
->window
);
1249 nsObjectFrame::IsFocusable(PRInt32
*aTabIndex
, PRBool aWithMouse
)
1253 return nsObjectFrameSuper::IsFocusable(aTabIndex
, aWithMouse
);
1257 nsObjectFrame::IsHidden(PRBool aCheckVisibilityStyle
) const
1259 if (aCheckVisibilityStyle
) {
1260 if (!GetStyleVisibility()->IsVisibleOrCollapsed())
1264 // only <embed> tags support the HIDDEN attribute
1265 if (mContent
->Tag() == nsGkAtoms::embed
) {
1266 // Yes, these are really the kooky ways that you could tell 4.x
1267 // not to hide the <embed> once you'd put the 'hidden' attribute
1270 // HIDDEN w/ no attributes gets translated as we are hidden for
1271 // compatibility w/ 4.x and IE so we don't create a non-painting
1272 // widget in layout. See bug 188959.
1273 nsAutoString hidden
;
1274 if (mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::hidden
, hidden
) &&
1275 (hidden
.IsEmpty() ||
1276 (!hidden
.LowerCaseEqualsLiteral("false") &&
1277 !hidden
.LowerCaseEqualsLiteral("no") &&
1278 !hidden
.LowerCaseEqualsLiteral("off")))) {
1286 nsIntPoint
nsObjectFrame::GetWindowOriginInPixels(PRBool aWindowless
)
1288 nsIView
* parentWithView
;
1289 nsPoint
origin(0,0);
1291 GetOffsetFromView(origin
, &parentWithView
);
1293 // if it's windowless, let's make sure we have our origin set right
1294 // it may need to be corrected, like after scrolling
1295 if (aWindowless
&& parentWithView
) {
1296 nsPoint offsetToWidget
;
1297 parentWithView
->GetNearestWidget(&offsetToWidget
);
1298 origin
+= offsetToWidget
;
1300 // It's OK to use GetUsedBorderAndPadding here (and below) since
1301 // GetSkipSides always returns 0; we don't split nsObjectFrames
1302 origin
+= GetUsedBorderAndPadding().TopLeft();
1304 return nsIntPoint(PresContext()->AppUnitsToDevPixels(origin
.x
),
1305 PresContext()->AppUnitsToDevPixels(origin
.y
));
1309 nsObjectFrame::DidReflow(nsPresContext
* aPresContext
,
1310 const nsHTMLReflowState
* aReflowState
,
1311 nsDidReflowStatus aStatus
)
1313 // Do this check before calling the superclass, as that clears
1314 // NS_FRAME_FIRST_REFLOW
1315 if (aStatus
== NS_FRAME_REFLOW_FINISHED
&&
1316 (GetStateBits() & NS_FRAME_FIRST_REFLOW
)) {
1317 nsCOMPtr
<nsIObjectLoadingContent
> objContent(do_QueryInterface(mContent
));
1318 NS_ASSERTION(objContent
, "Why not an object loading content?");
1319 objContent
->HasNewFrame(this);
1322 nsresult rv
= nsObjectFrameSuper::DidReflow(aPresContext
, aReflowState
, aStatus
);
1324 // The view is created hidden; once we have reflowed it and it has been
1325 // positioned then we show it.
1326 if (aStatus
!= NS_FRAME_REFLOW_FINISHED
)
1330 nsIView
* view
= GetView();
1331 nsIViewManager
* vm
= view
->GetViewManager();
1333 vm
->SetViewVisibility(view
, IsHidden() ? nsViewVisibility_kHide
: nsViewVisibility_kShow
);
1340 nsObjectFrame::PaintPrintPlugin(nsIFrame
* aFrame
, nsIRenderingContext
* aCtx
,
1341 const nsRect
& aDirtyRect
, nsPoint aPt
)
1343 nsPoint pt
= aPt
+ aFrame
->GetUsedBorderAndPadding().TopLeft();
1344 nsIRenderingContext::AutoPushTranslation
translate(aCtx
, pt
.x
, pt
.y
);
1345 // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
1346 static_cast<nsObjectFrame
*>(aFrame
)->PrintPlugin(*aCtx
, aDirtyRect
);
1349 class nsDisplayPluginReadback
: public nsDisplayItem
{
1351 nsDisplayPluginReadback(nsDisplayListBuilder
* aBuilder
, nsIFrame
* aFrame
)
1352 : nsDisplayItem(aBuilder
, aFrame
)
1354 MOZ_COUNT_CTOR(nsDisplayPluginReadback
);
1356 #ifdef NS_BUILD_REFCNT_LOGGING
1357 virtual ~nsDisplayPluginReadback() {
1358 MOZ_COUNT_DTOR(nsDisplayPluginReadback
);
1362 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
);
1363 virtual PRBool
ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
1364 nsRegion
* aVisibleRegion
,
1365 const nsRect
& aAllowVisibleRegionExpansion
,
1366 PRBool
& aContainsRootContentDocBG
);
1368 NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK
)
1370 virtual already_AddRefed
<Layer
> BuildLayer(nsDisplayListBuilder
* aBuilder
,
1371 LayerManager
* aManager
)
1373 return static_cast<nsObjectFrame
*>(mFrame
)->BuildLayer(aBuilder
, aManager
, this);
1376 virtual LayerState
GetLayerState(nsDisplayListBuilder
* aBuilder
,
1377 LayerManager
* aManager
)
1379 return LAYER_ACTIVE
;
1384 GetDesiredDisplayItemBounds(nsDisplayListBuilder
* aBuilder
, nsDisplayItem
* aItem
, nsIFrame
* aFrame
)
1386 nsRect r
= aFrame
->GetContentRect() - aFrame
->GetPosition() +
1387 aItem
->ToReferenceFrame();
1392 GetDrawnDisplayItemBounds(nsDisplayListBuilder
* aBuilder
, nsDisplayItem
* aItem
, nsIFrame
* aFrame
)
1394 nsRect r
= aFrame
->GetContentRect() - aFrame
->GetPosition() +
1395 aItem
->ToReferenceFrame();
1398 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(aFrame
);
1399 if (LAYER_ACTIVE
== f
->GetLayerState(aBuilder
, nsnull
)) {
1400 ImageContainer
* c
= f
->GetImageContainer();
1402 gfxIntSize size
= c
->GetCurrentSize();
1403 PRInt32 appUnitsPerDevPixel
= f
->PresContext()->AppUnitsPerDevPixel();
1404 nsSize
sizeAppUnits(size
.width
*appUnitsPerDevPixel
, size
.height
*appUnitsPerDevPixel
);
1405 r
+= nsPoint((r
.width
- sizeAppUnits
.width
) / 2,
1406 (r
.height
- sizeAppUnits
.height
) / 2);
1407 r
.SizeTo(sizeAppUnits
);
1415 nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder
* aBuilder
)
1417 return GetDesiredDisplayItemBounds(aBuilder
, this, mFrame
);
1421 nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
1422 nsRegion
* aVisibleRegion
,
1423 const nsRect
& aAllowVisibleRegionExpansion
,
1424 PRBool
& aContainsRootContentDocBG
)
1426 if (!nsDisplayItem::ComputeVisibility(aBuilder
, aVisibleRegion
,
1427 aAllowVisibleRegionExpansion
,
1428 aContainsRootContentDocBG
))
1432 expand
.IntersectRect(aAllowVisibleRegionExpansion
, GetBounds(aBuilder
));
1433 // *Add* our bounds to the visible region so that stuff underneath us is
1434 // likely to be made visible, so we can use it for a background! This is
1435 // a bit crazy since we normally only subtract from the visible region.
1436 aVisibleRegion
->Or(*aVisibleRegion
, expand
);
1441 nsDisplayPlugin::GetBounds(nsDisplayListBuilder
* aBuilder
)
1443 // We use display lists to notify plugins of visibility. But we
1444 // also need to return the "real" visible bounds, possibly those of
1445 // our Image, when actually painting. Usually those will be the
1446 // same, but for the plugin to paint initially, something needs to
1447 // notify it that it's visible. So return whichever the appropriate
1449 return aBuilder
->IsForPluginGeometry() ?
1450 GetDesiredDisplayItemBounds(aBuilder
, this, mFrame
) :
1451 GetDrawnDisplayItemBounds(aBuilder
, this, mFrame
);
1455 nsDisplayPlugin::Paint(nsDisplayListBuilder
* aBuilder
,
1456 nsIRenderingContext
* aCtx
)
1458 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(mFrame
);
1459 f
->PaintPlugin(aBuilder
, *aCtx
, mVisibleRect
, GetBounds(aBuilder
));
1463 nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder
* aBuilder
,
1464 nsRegion
* aVisibleRegion
,
1465 const nsRect
& aAllowVisibleRegionExpansion
,
1466 PRBool
& aContainsRootContentDocBG
)
1468 mVisibleRegion
.And(*aVisibleRegion
, GetBounds(aBuilder
));
1469 return nsDisplayItem::ComputeVisibility(aBuilder
, aVisibleRegion
,
1470 aAllowVisibleRegionExpansion
,
1471 aContainsRootContentDocBG
);
1475 nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder
* aBuilder
,
1476 PRBool
* aForceTransparentSurface
)
1478 if (aForceTransparentSurface
) {
1479 *aForceTransparentSurface
= PR_FALSE
;
1482 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(mFrame
);
1483 if (!aBuilder
->IsForPluginGeometry()) {
1484 nsIWidget
* widget
= f
->GetWidget();
1486 nsTArray
<nsIntRect
> clip
;
1487 widget
->GetWindowClipRegion(&clip
);
1488 nsTArray
<nsIWidget::Configuration
> configuration
;
1489 GetWidgetConfiguration(aBuilder
, &configuration
);
1490 NS_ASSERTION(configuration
.Length() == 1, "No configuration found");
1491 if (clip
!= configuration
[0].mClipRegion
) {
1492 // Something has clipped us unexpectedly. Perhaps there is a translucent
1493 // chrome element overlaying us that forced us to be clipped away. Treat
1494 // us as non-opaque since we may have holes.
1499 if (f
->IsOpaque()) {
1500 result
= GetBounds(aBuilder
);
1506 nsDisplayPlugin::GetWidgetConfiguration(nsDisplayListBuilder
* aBuilder
,
1507 nsTArray
<nsIWidget::Configuration
>* aConfigurations
)
1509 nsObjectFrame
* f
= static_cast<nsObjectFrame
*>(mFrame
);
1510 nsPoint pluginOrigin
= mFrame
->GetUsedBorderAndPadding().TopLeft() +
1512 f
->ComputeWidgetGeometry(mVisibleRegion
, pluginOrigin
, aConfigurations
);
1516 nsObjectFrame::ComputeWidgetGeometry(const nsRegion
& aRegion
,
1517 const nsPoint
& aPluginOrigin
,
1518 nsTArray
<nsIWidget::Configuration
>* aConfigurations
)
1522 if (mInstanceOwner
) {
1523 // UpdateWindowVisibility will notify the plugin of position changes
1524 // by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
1525 mInstanceOwner
->UpdateWindowVisibility(!aRegion
.IsEmpty());
1531 nsPresContext
* presContext
= PresContext();
1532 nsRootPresContext
* rootPC
= presContext
->GetRootPresContext();
1536 nsIWidget::Configuration
* configuration
= aConfigurations
->AppendElement();
1539 configuration
->mChild
= mWidget
;
1541 PRInt32 appUnitsPerDevPixel
= presContext
->AppUnitsPerDevPixel();
1542 nsIFrame
* rootFrame
= rootPC
->PresShell()->FrameManager()->GetRootFrame();
1543 nsRect bounds
= GetContentRect() + GetParent()->GetOffsetToCrossDoc(rootFrame
);
1544 configuration
->mBounds
= bounds
.ToNearestPixels(appUnitsPerDevPixel
);
1546 // This should produce basically the same rectangle (but not relative
1547 // to the root frame). We only call this here for the side-effect of
1548 // setting mViewToWidgetOffset on the view.
1549 mInnerView
->CalcWidgetBounds(eWindowType_plugin
);
1551 nsRegionRectIterator
iter(aRegion
);
1552 nsIntPoint pluginOrigin
= aPluginOrigin
.ToNearestPixels(appUnitsPerDevPixel
);
1553 for (const nsRect
* r
= iter
.Next(); r
; r
= iter
.Next()) {
1554 // Snap *r to pixels while it's relative to the painted widget, to
1555 // improve consistency with rectangle and image drawing
1557 r
->ToNearestPixels(appUnitsPerDevPixel
) - pluginOrigin
;
1558 if (!pixRect
.IsEmpty()) {
1559 configuration
->mClipRegion
.AppendElement(pixRect
);
1565 nsObjectFrame::SetAbsoluteScreenPosition(nsIDOMElement
* element
,
1566 nsIDOMClientRect
* position
,
1567 nsIDOMClientRect
* clip
)
1569 #ifdef MOZ_USE_IMAGE_EXPOSE
1570 if (!mInstanceOwner
)
1571 return NS_ERROR_NOT_AVAILABLE
;
1572 return mInstanceOwner
->SetAbsoluteScreenPosition(element
, position
, clip
);
1574 return NS_ERROR_NOT_IMPLEMENTED
;
1579 nsObjectFrame::PluginEventNotifier::Run() {
1580 nsCOMPtr
<nsIObserverService
> obsSvc
=
1581 mozilla::services::GetObserverService();
1582 obsSvc
->NotifyObservers(nsnull
, "plugin-changed-event", mEventType
.get());
1587 nsObjectFrame::NotifyPluginReflowObservers()
1589 nsContentUtils::AddScriptRunner(new PluginEventNotifier(NS_LITERAL_STRING("reflow")));
1593 nsObjectFrame::DidSetWidgetGeometry()
1595 #if defined(XP_MACOSX)
1596 if (mInstanceOwner
) {
1597 mInstanceOwner
->FixUpPluginWindow(ePluginPaintEnable
);
1603 nsObjectFrame::IsOpaque() const
1605 #if defined(XP_MACOSX)
1609 return !IsTransparentMode();
1614 nsObjectFrame::IsTransparentMode() const
1616 #if defined(XP_MACOSX)
1620 if (!mInstanceOwner
)
1624 mInstanceOwner
->GetWindow(window
);
1625 if (window
->type
!= NPWindowTypeDrawable
)
1629 nsCOMPtr
<nsIPluginInstance
> pi
;
1630 rv
= mInstanceOwner
->GetInstance(*getter_AddRefs(pi
));
1631 if (NS_FAILED(rv
) || !pi
)
1634 PRBool transparent
= PR_FALSE
;
1635 pi
->IsTransparent(&transparent
);
1641 nsObjectFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
1642 const nsRect
& aDirtyRect
,
1643 const nsDisplayListSet
& aLists
)
1645 AddStateBits(NS_OBJECT_NEEDS_SET_IMAGE
);
1647 // XXX why are we painting collapsed object frames?
1648 if (!IsVisibleOrCollapsedForPainting(aBuilder
))
1651 nsresult rv
= DisplayBorderBackgroundOutline(aBuilder
, aLists
);
1652 NS_ENSURE_SUCCESS(rv
, rv
);
1654 nsPresContext::nsPresContextType type
= PresContext()->Type();
1656 // If we are painting in Print Preview do nothing....
1657 if (type
== nsPresContext::eContext_PrintPreview
)
1660 DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame");
1663 if (mWidget
&& aBuilder
->IsInTransform()) {
1664 // Windowed plugins should not be rendered inside a transform.
1669 nsDisplayList replacedContent
;
1671 if (aBuilder
->IsForPainting() && mInstanceOwner
&& mInstanceOwner
->UseAsyncRendering()) {
1672 NPWindow
* window
= nsnull
;
1673 mInstanceOwner
->GetWindow(window
);
1674 PRBool isVisible
= window
&& window
->width
> 0 && window
->height
> 0;
1675 if (isVisible
&& aBuilder
->ShouldSyncDecodeImages()) {
1677 mInstanceOwner
->UpdateWindowVisibility(PR_TRUE
);
1681 ImageContainer
* container
= GetImageContainer();
1682 nsRefPtr
<Image
> currentImage
= container
? container
->GetCurrentImage() : nsnull
;
1683 if (!currentImage
|| !isVisible
||
1684 container
->GetCurrentSize() != gfxIntSize(window
->width
, window
->height
)) {
1685 mInstanceOwner
->NotifyPaintWaiter(aBuilder
);
1689 // determine if we are printing
1690 if (type
== nsPresContext::eContext_Print
) {
1691 rv
= replacedContent
.AppendNewToTop(new (aBuilder
)
1692 nsDisplayGeneric(aBuilder
, this, PaintPrintPlugin
, "PrintPlugin",
1693 nsDisplayItem::TYPE_PRINT_PLUGIN
));
1695 if (aBuilder
->IsPaintingToWindow() &&
1696 GetLayerState(aBuilder
, nsnull
) == LAYER_ACTIVE
&&
1697 IsTransparentMode()) {
1698 rv
= replacedContent
.AppendNewToTop(new (aBuilder
)
1699 nsDisplayPluginReadback(aBuilder
, this));
1700 NS_ENSURE_SUCCESS(rv
, rv
);
1703 rv
= replacedContent
.AppendNewToTop(new (aBuilder
)
1704 nsDisplayPlugin(aBuilder
, this));
1706 NS_ENSURE_SUCCESS(rv
, rv
);
1708 WrapReplacedContentForBorderRadius(aBuilder
, &replacedContent
, aLists
);
1714 nsObjectFrame::PrintPlugin(nsIRenderingContext
& aRenderingContext
,
1715 const nsRect
& aDirtyRect
)
1717 nsCOMPtr
<nsIObjectLoadingContent
> obj(do_QueryInterface(mContent
));
1721 nsIFrame
* frame
= nsnull
;
1722 obj
->GetPrintFrame(&frame
);
1726 nsPresContext
* presContext
= PresContext();
1727 // make sure this is REALLY an nsIObjectFrame
1728 // we may need to go through the children to get it
1729 nsIObjectFrame
* objectFrame
= do_QueryFrame(frame
);
1731 objectFrame
= GetNextObjectFrame(presContext
,frame
);
1735 // finally we can get our plugin instance
1736 nsCOMPtr
<nsIPluginInstance
> pi
;
1737 if (NS_FAILED(objectFrame
->GetPluginInstance(*getter_AddRefs(pi
))) || !pi
)
1740 // now we need to setup the correct location for printing
1742 window
.window
= nsnull
;
1744 // prepare embedded mode printing struct
1746 npprint
.mode
= NP_EMBED
;
1748 // we need to find out if we are windowless or not
1749 PRBool windowless
= PR_FALSE
;
1750 pi
->IsWindowless(&windowless
);
1751 window
.type
= windowless
? NPWindowTypeDrawable
: NPWindowTypeWindow
;
1753 window
.clipRect
.bottom
= 0; window
.clipRect
.top
= 0;
1754 window
.clipRect
.left
= 0; window
.clipRect
.right
= 0;
1756 // platform specific printing code
1757 #ifdef MAC_CARBON_PLUGINS
1758 nsSize contentSize
= GetContentRect().Size();
1761 window
.width
= presContext
->AppUnitsToDevPixels(contentSize
.width
);
1762 window
.height
= presContext
->AppUnitsToDevPixels(contentSize
.height
);
1764 gfxContext
*ctx
= aRenderingContext
.ThebesContext();
1767 gfxContextAutoSaveRestore
save(ctx
);
1771 gfxRect
rect(window
.x
, window
.y
, window
.width
, window
.height
);
1773 ctx
->Rectangle(rect
);
1776 gfxQuartzNativeDrawing
nativeDraw(ctx
, rect
);
1777 CGContextRef cgContext
= nativeDraw
.BeginNativeDrawing();
1779 nativeDraw
.EndNativeDrawing();
1783 window
.clipRect
.right
= window
.width
;
1784 window
.clipRect
.bottom
= window
.height
;
1785 window
.type
= NPWindowTypeDrawable
;
1788 ::SetRect(&gwBounds
, 0, 0, window
.width
, window
.height
);
1790 nsTArray
<char> buffer(window
.width
* window
.height
* 4);
1791 CGColorSpaceRef cspace
= ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB
);
1793 nativeDraw
.EndNativeDrawing();
1796 CGContextRef cgBuffer
=
1797 ::CGBitmapContextCreate(buffer
.Elements(),
1798 window
.width
, window
.height
, 8, window
.width
* 4,
1799 cspace
, kCGBitmapByteOrder32Big
| kCGImageAlphaPremultipliedFirst
);
1800 ::CGColorSpaceRelease(cspace
);
1802 nativeDraw
.EndNativeDrawing();
1806 if (::NewGWorldFromPtr(&gWorld
, k32ARGBPixelFormat
, &gwBounds
, NULL
, NULL
, 0,
1807 buffer
.Elements(), window
.width
* 4) != noErr
) {
1808 ::CGContextRelease(cgBuffer
);
1809 nativeDraw
.EndNativeDrawing();
1813 window
.clipRect
.right
= window
.width
;
1814 window
.clipRect
.bottom
= window
.height
;
1815 window
.type
= NPWindowTypeDrawable
;
1816 // Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
1817 // &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
1818 // GWorldPtr isn't any kind of standard (it's not documented anywhere).
1819 // But that's what WebKit does. And it's what the Flash plugin (apparently
1820 // the only NPAPI plugin on OS X to support printing) seems to expect. So
1821 // we do the same. The Flash plugin uses the CoreGraphics drawing mode.
1822 // But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
1823 // drawing mode. See bug 191046.
1824 window
.window
= &gWorld
;
1825 npprint
.print
.embedPrint
.platformPrint
= gWorld
;
1826 npprint
.print
.embedPrint
.window
= window
;
1827 nsresult rv
= pi
->Print(&npprint
);
1829 ::CGContextTranslateCTM(cgContext
, 0.0f
, float(window
.height
));
1830 ::CGContextScaleCTM(cgContext
, 1.0f
, -1.0f
);
1831 CGImageRef image
= ::CGBitmapContextCreateImage(cgBuffer
);
1833 ::CGContextRestoreGState(cgContext
);
1834 ::CGContextRelease(cgBuffer
);
1835 ::DisposeGWorld(gWorld
);
1836 nativeDraw
.EndNativeDrawing();
1839 ::CGContextDrawImage(cgContext
,
1840 ::CGRectMake(0, 0, window
.width
, window
.height
),
1842 ::CGImageRelease(image
);
1843 ::CGContextRelease(cgBuffer
);
1845 ::DisposeGWorld(gWorld
);
1847 nativeDraw
.EndNativeDrawing();
1848 #elif defined(XP_UNIX)
1850 /* XXX this just flat-out doesn't work in a thebes world --
1851 * RenderEPS is a no-op. So don't bother to do any work here.
1854 #elif defined(XP_OS2)
1855 void *hps
= aRenderingContext
.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS
);
1859 npprint
.print
.embedPrint
.platformPrint
= hps
;
1860 npprint
.print
.embedPrint
.window
= window
;
1861 // send off print info to plugin
1862 pi
->Print(&npprint
);
1863 #elif defined(XP_WIN)
1865 /* On Windows, we use the win32 printing surface to print. This, in
1866 * turn, uses the Cairo paginated surface, which in turn uses the
1867 * meta surface to record all operations and then play them back.
1868 * This doesn't work too well for plugins, because if plugins render
1869 * directly into the DC, the meta surface won't have any knowledge
1870 * of them, and so at the end when it actually does the replay step,
1871 * it'll fill the background with white and draw over whatever was
1874 * So, to avoid this, we use PushGroup, which creates a new windows
1875 * surface, the plugin renders to that, and then we use normal
1876 * cairo methods to composite that in such that it's recorded using the
1880 /* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
1881 nsSize contentSize
= GetContentRect().Size();
1884 window
.width
= presContext
->AppUnitsToDevPixels(contentSize
.width
);
1885 window
.height
= presContext
->AppUnitsToDevPixels(contentSize
.height
);
1887 gfxContext
*ctx
= aRenderingContext
.ThebesContext();
1891 /* Make sure plugins don't do any damage outside of where they're supposed to */
1893 gfxRect
r(window
.x
, window
.y
, window
.width
, window
.height
);
1897 gfxWindowsNativeDrawing
nativeDraw(ctx
, r
);
1899 HDC dc
= nativeDraw
.BeginNativeDrawing();
1903 // XXX don't we need to call nativeDraw.TransformToNativeRect here?
1904 npprint
.print
.embedPrint
.platformPrint
= dc
;
1905 npprint
.print
.embedPrint
.window
= window
;
1906 // send off print info to plugin
1907 pi
->Print(&npprint
);
1909 nativeDraw
.EndNativeDrawing();
1910 } while (nativeDraw
.ShouldRenderAgain());
1911 nativeDraw
.PaintToContext();
1916 // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
1917 // XXX Calling DidReflow here makes no sense!!!
1918 nsDidReflowStatus status
= NS_FRAME_REFLOW_FINISHED
; // should we use a special status?
1919 frame
->DidReflow(presContext
,
1920 nsnull
, status
); // DidReflow will take care of it
1924 nsObjectFrame::GetImageContainer(LayerManager
* aManager
)
1926 nsRefPtr
<LayerManager
> manager
= aManager
;
1929 manager
= nsContentUtils::LayerManagerForDocument(mContent
->GetOwnerDoc());
1935 // XXX - in the future image containers will be manager independent and
1936 // we can remove the manager equals check and only check the backend type.
1937 if (mImageContainer
&&
1938 (!mImageContainer
->Manager() || mImageContainer
->Manager() == manager
) &&
1939 mImageContainer
->GetBackendType() == manager
->GetBackendType()) {
1940 return mImageContainer
;
1943 mImageContainer
= manager
->CreateImageContainer();
1944 return mImageContainer
;
1947 class AsyncPaintWaitEvent
: public nsRunnable
1950 AsyncPaintWaitEvent(nsIContent
* aContent
, PRBool aFinished
) :
1951 mContent(aContent
), mFinished(aFinished
)
1957 nsContentUtils::DispatchTrustedEvent(mContent
->GetOwnerDoc(), mContent
,
1958 mFinished
? NS_LITERAL_STRING("MozPaintWaitFinished") : NS_LITERAL_STRING("MozPaintWait"),
1964 nsCOMPtr
<nsIContent
> mContent
;
1965 PRPackedBool mFinished
;
1969 nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder
* aBuilder
)
1971 // This is notification for reftests about async plugin paint start
1972 if (!mWaitingForPaint
&& !IsUpToDate() && aBuilder
->ShouldSyncDecodeImages()) {
1973 nsCOMPtr
<nsIRunnable
> event
= new AsyncPaintWaitEvent(mContent
, PR_FALSE
);
1974 // Run this event as soon as it's safe to do so, since listeners need to
1975 // receive it immediately
1976 mWaitingForPaint
= nsContentUtils::AddScriptRunner(event
);
1980 static void DrawPlugin(ImageContainer
* aContainer
, void* aObjectFrame
)
1982 static_cast<nsObjectFrame
*>(aObjectFrame
)->UpdateImageLayer(aContainer
, gfxRect(0,0,0,0));
1986 nsObjectFrame::UpdateImageLayer(ImageContainer
* aContainer
, const gfxRect
& aRect
)
1989 mInstanceOwner
->DoCocoaEventDrawRect(aRect
, nsnull
);
1992 mInstanceOwner
->SetCurrentImage(aContainer
);
1996 nsPluginInstanceOwner::SetCurrentImage(ImageContainer
* aContainer
)
1998 nsCOMPtr
<nsIPluginInstance_MOZILLA_2_0_BRANCH
> inst
= do_QueryInterface(mInstance
);
2000 nsRefPtr
<Image
> image
;
2001 inst
->GetImage(aContainer
, getter_AddRefs(image
));
2004 if (image
->GetFormat() == Image::MAC_IO_SURFACE
) {
2005 MacIOSurfaceImage
*oglImage
= static_cast<MacIOSurfaceImage
*>(image
.get());
2006 oglImage
->SetCallback(&DrawPlugin
, mObjectFrame
);
2009 aContainer
->SetCurrentImage(image
);
2013 aContainer
->SetCurrentImage(nsnull
);
2018 nsPluginInstanceOwner::SetBackgroundUnknown()
2020 nsCOMPtr
<nsIPluginInstance_MOZILLA_2_0_BRANCH
> inst
= GetInstance();
2022 inst
->SetBackgroundUnknown();
2026 already_AddRefed
<gfxContext
>
2027 nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect
& aRect
)
2029 nsIntRect rect
= aRect
;
2030 nsCOMPtr
<nsIPluginInstance_MOZILLA_2_0_BRANCH
> inst
= GetInstance();
2031 nsRefPtr
<gfxContext
> ctx
;
2033 NS_SUCCEEDED(inst
->BeginUpdateBackground(&rect
, getter_AddRefs(ctx
)))) {
2034 return ctx
.forget();
2040 nsPluginInstanceOwner::EndUpdateBackground(gfxContext
* aContext
,
2041 const nsIntRect
& aRect
)
2043 nsIntRect rect
= aRect
;
2044 nsCOMPtr
<nsIPluginInstance_MOZILLA_2_0_BRANCH
> inst
= GetInstance();
2046 inst
->EndUpdateBackground(aContext
, &rect
);
2051 nsObjectFrame::GetLayerState(nsDisplayListBuilder
* aBuilder
,
2052 LayerManager
* aManager
)
2054 if (!mInstanceOwner
)
2055 return mozilla::LAYER_NONE
;
2059 aManager
->GetBackendType() == LayerManager::LAYERS_OPENGL
&&
2060 mInstanceOwner
->GetEventModel() == NPEventModelCocoa
&&
2061 mInstanceOwner
->GetDrawingModel() == NPDrawingModelCoreGraphics
&&
2062 mInstanceOwner
->IsRemoteDrawingCoreAnimation())
2064 return mozilla::LAYER_ACTIVE
;
2068 if (!mInstanceOwner
->UseAsyncRendering())
2069 return mozilla::LAYER_NONE
;
2071 return mozilla::LAYER_ACTIVE
;
2074 already_AddRefed
<Layer
>
2075 nsObjectFrame::BuildLayer(nsDisplayListBuilder
* aBuilder
,
2076 LayerManager
* aManager
,
2077 nsDisplayItem
* aItem
)
2079 if (!mInstanceOwner
)
2082 NPWindow
* window
= nsnull
;
2083 mInstanceOwner
->GetWindow(window
);
2087 if (window
->width
<= 0 || window
->height
<= 0)
2091 nsRefPtr
<ImageContainer
> container
= GetImageContainer(aManager
);
2094 if (GetStateBits() & NS_OBJECT_NEEDS_SET_IMAGE
) {
2095 RemoveStateBits(NS_OBJECT_NEEDS_SET_IMAGE
);
2096 if (!mInstanceOwner
->SetCurrentImage(container
)) {
2100 gfxIntSize size
= container
->GetCurrentSize();
2102 nsRect area
= GetContentRect() + aBuilder
->ToReferenceFrame(GetParent());
2103 gfxRect r
= nsLayoutUtils::RectToGfxRect(area
, PresContext()->AppUnitsPerDevPixel());
2104 // to provide crisper and faster drawing.
2106 nsRefPtr
<Layer
> layer
=
2107 (aBuilder
->LayerBuilder()->GetLeafLayerFor(aBuilder
, aManager
, aItem
));
2109 if (aItem
->GetType() == nsDisplayItem::TYPE_PLUGIN
) {
2111 mInstanceOwner
->NotifyPaintWaiter(aBuilder
);
2112 // Initialize ImageLayer
2113 layer
= aManager
->CreateImageLayer();
2118 NS_ASSERTION(layer
->GetType() == Layer::TYPE_IMAGE
, "Bad layer type");
2120 ImageLayer
* imglayer
= static_cast<ImageLayer
*>(layer
.get());
2121 UpdateImageLayer(container
, r
);
2123 imglayer
->SetContainer(container
);
2124 imglayer
->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
2126 layer
->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE
: 0);
2128 NS_ASSERTION(aItem
->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK
,
2129 "Unknown item type");
2130 NS_ABORT_IF_FALSE(!IsOpaque(), "Opaque plugins don't use backgrounds");
2133 layer
= aManager
->CreateReadbackLayer();
2137 NS_ASSERTION(layer
->GetType() == Layer::TYPE_READBACK
, "Bad layer type");
2139 ReadbackLayer
* readback
= static_cast<ReadbackLayer
*>(layer
.get());
2140 if (readback
->GetSize() != nsIntSize(size
.width
, size
.height
)) {
2141 // This will destroy any old background sink and notify us that the
2142 // background is now unknown
2143 readback
->SetSink(nsnull
);
2144 NS_ASSERTION(!mBackgroundSink
, "Should have been cleared");
2146 readback
->SetSize(nsIntSize(size
.width
, size
.height
));
2149 new PluginBackgroundSink(this,
2150 readback
->AllocateSequenceNumber());
2151 readback
->SetSink(mBackgroundSink
);
2152 // The layer has taken ownership of our sink. When either the sink dies
2153 // or the frame dies, the connection from the surviving object is nulled out.
2157 // Set a transform on the layer to draw the plugin in the right place
2158 gfxMatrix transform
;
2159 // Center plugin if layer size != frame rect
2160 r
.pos
.x
+= (r
.Width() - size
.width
) / 2;
2161 r
.pos
.y
+= (r
.Height() - size
.height
) / 2;
2162 transform
.Translate(r
.pos
);
2164 layer
->SetTransform(gfx3DMatrix::From2D(transform
));
2165 return layer
.forget();
2169 nsObjectFrame::PaintPlugin(nsDisplayListBuilder
* aBuilder
,
2170 nsIRenderingContext
& aRenderingContext
,
2171 const nsRect
& aDirtyRect
, const nsRect
& aPluginRect
)
2173 // Screen painting code
2174 #if defined(XP_MACOSX)
2175 // delegate all painting to the plugin instance.
2176 if (mInstanceOwner
) {
2177 if (mInstanceOwner
->GetDrawingModel() == NPDrawingModelCoreGraphics
||
2178 mInstanceOwner
->GetDrawingModel() == NPDrawingModelCoreAnimation
||
2179 mInstanceOwner
->GetDrawingModel() ==
2180 NPDrawingModelInvalidatingCoreAnimation
) {
2181 PRInt32 appUnitsPerDevPixel
= PresContext()->AppUnitsPerDevPixel();
2182 // Clip to the content area where the plugin should be drawn. If
2183 // we don't do this, the plugin can draw outside its bounds.
2184 nsIntRect contentPixels
= aPluginRect
.ToNearestPixels(appUnitsPerDevPixel
);
2185 nsIntRect dirtyPixels
= aDirtyRect
.ToOutsidePixels(appUnitsPerDevPixel
);
2186 nsIntRect clipPixels
;
2187 clipPixels
.IntersectRect(contentPixels
, dirtyPixels
);
2189 // Don't invoke the drawing code if the clip is empty.
2190 if (clipPixels
.IsEmpty())
2193 gfxRect
nativeClipRect(clipPixels
.x
, clipPixels
.y
,
2194 clipPixels
.width
, clipPixels
.height
);
2195 gfxContext
* ctx
= aRenderingContext
.ThebesContext();
2197 gfxContextAutoSaveRestore
save(ctx
);
2199 ctx
->Rectangle(nativeClipRect
);
2201 gfxPoint
offset(contentPixels
.x
, contentPixels
.y
);
2202 ctx
->Translate(offset
);
2204 gfxQuartzNativeDrawing
nativeDrawing(ctx
, nativeClipRect
- offset
);
2206 CGContextRef cgContext
= nativeDrawing
.BeginNativeDrawing();
2208 NS_WARNING("null CGContextRef during PaintPlugin");
2212 nsCOMPtr
<nsIPluginInstance
> inst
;
2213 GetPluginInstance(*getter_AddRefs(inst
));
2215 NS_WARNING("null plugin instance during PaintPlugin");
2216 nativeDrawing
.EndNativeDrawing();
2220 mInstanceOwner
->GetWindow(window
);
2222 NS_WARNING("null plugin window during PaintPlugin");
2223 nativeDrawing
.EndNativeDrawing();
2226 NP_CGContext
* cgPluginPortCopy
=
2227 static_cast<NP_CGContext
*>(mInstanceOwner
->GetPluginPortCopy());
2228 if (!cgPluginPortCopy
) {
2229 NS_WARNING("null plugin port copy during PaintPlugin");
2230 nativeDrawing
.EndNativeDrawing();
2233 #ifndef NP_NO_CARBON
2234 if (mInstanceOwner
->GetEventModel() == NPEventModelCarbon
&&
2235 !mInstanceOwner
->SetPluginPortAndDetectChange()) {
2236 NS_WARNING("null plugin port during PaintPlugin");
2237 nativeDrawing
.EndNativeDrawing();
2241 // In the Carbon event model...
2242 // If gfxQuartzNativeDrawing hands out a CGContext different from the
2243 // one set by SetPluginPortAndDetectChange(), we need to pass it to the
2244 // plugin via SetWindow(). This will happen in nsPluginInstanceOwner::
2245 // FixUpPluginWindow(), called from nsPluginInstanceOwner::Paint().
2246 // (If SetPluginPortAndDetectChange() made any changes itself, this has
2247 // already been detected in that method, and will likewise result in a
2248 // call to SetWindow() from FixUpPluginWindow().)
2249 NP_CGContext
* windowContext
= static_cast<NP_CGContext
*>(window
->window
);
2250 if (mInstanceOwner
->GetEventModel() == NPEventModelCarbon
&&
2251 windowContext
->context
!= cgContext
) {
2252 windowContext
->context
= cgContext
;
2253 cgPluginPortCopy
->context
= cgContext
;
2254 mInstanceOwner
->SetPluginPortChanged(PR_TRUE
);
2258 mInstanceOwner
->BeginCGPaint();
2259 if (mInstanceOwner
->GetDrawingModel() == NPDrawingModelCoreAnimation
||
2260 mInstanceOwner
->GetDrawingModel() ==
2261 NPDrawingModelInvalidatingCoreAnimation
) {
2262 // CoreAnimation is updated, render the layer and perform a readback.
2263 mInstanceOwner
->RenderCoreAnimation(cgContext
, window
->width
, window
->height
);
2265 mInstanceOwner
->Paint(nativeClipRect
- offset
, cgContext
);
2267 mInstanceOwner
->EndCGPaint();
2269 nativeDrawing
.EndNativeDrawing();
2271 // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
2272 nsIRenderingContext::AutoPushTranslation
2273 translate(&aRenderingContext
, aPluginRect
.x
, aPluginRect
.y
);
2275 // this rect is used only in the CoreGraphics drawing model
2276 gfxRect
tmpRect(0, 0, 0, 0);
2277 mInstanceOwner
->Paint(tmpRect
, NULL
);
2280 #elif defined(MOZ_X11)
2281 if (mInstanceOwner
) {
2283 mInstanceOwner
->GetWindow(window
);
2284 #ifdef MOZ_COMPOSITED_PLUGINS
2287 if (window
->type
== NPWindowTypeDrawable
) {
2289 gfxRect frameGfxRect
=
2290 PresContext()->AppUnitsToGfxUnits(aPluginRect
);
2291 gfxRect dirtyGfxRect
=
2292 PresContext()->AppUnitsToGfxUnits(aDirtyRect
);
2293 gfxContext
* ctx
= aRenderingContext
.ThebesContext();
2295 mInstanceOwner
->Paint(ctx
, frameGfxRect
, dirtyGfxRect
);
2298 #elif defined(XP_WIN)
2299 nsCOMPtr
<nsIPluginInstance
> inst
;
2300 GetPluginInstance(*getter_AddRefs(inst
));
2302 gfxRect frameGfxRect
=
2303 PresContext()->AppUnitsToGfxUnits(aPluginRect
);
2304 gfxRect dirtyGfxRect
=
2305 PresContext()->AppUnitsToGfxUnits(aDirtyRect
);
2306 gfxContext
*ctx
= aRenderingContext
.ThebesContext();
2307 gfxMatrix currentMatrix
= ctx
->CurrentMatrix();
2309 if (ctx
->UserToDevicePixelSnapped(frameGfxRect
, PR_FALSE
)) {
2310 dirtyGfxRect
= ctx
->UserToDevice(dirtyGfxRect
);
2311 ctx
->IdentityMatrix();
2313 dirtyGfxRect
.RoundOut();
2315 // Look if it's windowless
2317 mInstanceOwner
->GetWindow(window
);
2319 if (window
->type
== NPWindowTypeDrawable
) {
2320 // the offset of the DC
2323 gfxWindowsNativeDrawing
nativeDraw(ctx
, frameGfxRect
);
2325 if (nativeDraw
.IsDoublePass()) {
2326 // OOP plugin specific: let the shim know before we paint if we are doing a
2327 // double pass render. If this plugin isn't oop, the register window message
2329 NPEvent pluginEvent
;
2330 pluginEvent
.event
= DoublePassRenderingEvent();
2331 pluginEvent
.wParam
= 0;
2332 pluginEvent
.lParam
= 0;
2333 if (pluginEvent
.event
)
2334 inst
->HandleEvent(&pluginEvent
, nsnull
);
2338 HDC hdc
= nativeDraw
.BeginNativeDrawing();
2343 nativeDraw
.TransformToNativeRect(frameGfxRect
, dest
);
2345 nativeDraw
.TransformToNativeRect(dirtyGfxRect
, dirty
);
2347 window
->window
= hdc
;
2348 window
->x
= dest
.left
;
2349 window
->y
= dest
.top
;
2350 window
->clipRect
.left
= 0;
2351 window
->clipRect
.top
= 0;
2352 // if we're painting, we're visible.
2353 window
->clipRect
.right
= window
->width
;
2354 window
->clipRect
.bottom
= window
->height
;
2356 // Windowless plugins on windows need a special event to update their location,
2359 // bug 271442: note, the rectangle we send is now purely the bounds of the plugin
2360 // relative to the window it is contained in, which is useful for the plugin to
2361 // correctly translate mouse coordinates.
2363 // this does not mesh with the comments for bug 135737 which imply that the rectangle
2364 // must be clipped in some way to prevent the plugin attempting to paint over areas
2367 // since the two uses of the rectangle are mutually exclusive in some cases, and
2368 // since I don't see any incorrect painting (at least with Flash and ViewPoint -
2369 // the originator of bug 135737), it seems that windowless plugins are not relying
2370 // on information here for clipping their drawing, and we can safely use this message
2371 // to tell the plugin exactly where it is in all cases.
2373 nsIntPoint origin
= GetWindowOriginInPixels(PR_TRUE
);
2374 nsIntRect winlessRect
= nsIntRect(origin
, nsIntSize(window
->width
, window
->height
));
2376 if (mWindowlessRect
!= winlessRect
) {
2377 mWindowlessRect
= winlessRect
;
2380 memset(&winpos
, 0, sizeof(winpos
));
2381 winpos
.x
= mWindowlessRect
.x
;
2382 winpos
.y
= mWindowlessRect
.y
;
2383 winpos
.cx
= mWindowlessRect
.width
;
2384 winpos
.cy
= mWindowlessRect
.height
;
2386 // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
2387 NPEvent pluginEvent
;
2388 pluginEvent
.event
= WM_WINDOWPOSCHANGED
;
2389 pluginEvent
.wParam
= 0;
2390 pluginEvent
.lParam
= (LPARAM
)&winpos
;
2391 inst
->HandleEvent(&pluginEvent
, nsnull
);
2394 inst
->SetWindow(window
);
2396 mInstanceOwner
->Paint(dirty
, hdc
);
2397 nativeDraw
.EndNativeDrawing();
2398 } while (nativeDraw
.ShouldRenderAgain());
2399 nativeDraw
.PaintToContext();
2402 ctx
->SetMatrix(currentMatrix
);
2404 #elif defined(XP_OS2)
2405 nsCOMPtr
<nsIPluginInstance
> inst
;
2406 GetPluginInstance(*getter_AddRefs(inst
));
2408 // Look if it's windowless
2410 mInstanceOwner
->GetWindow(window
);
2412 if (window
->type
== NPWindowTypeDrawable
) {
2413 // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
2414 nsIRenderingContext::AutoPushTranslation
2415 translate(&aRenderingContext
, aPluginRect
.x
, aPluginRect
.y
);
2417 // check if we need to call SetWindow with updated parameters
2418 PRBool doupdatewindow
= PR_FALSE
;
2419 // the offset of the DC
2423 * Layout now has an optimized way of painting. Now we always get
2424 * a new drawing surface, sized to be just what's needed. Windowless
2425 * plugins need a transform applied to their origin so they paint
2426 * in the right place. Since |SetWindow| is no longer being used
2427 * to tell the plugin where it is, we dispatch a NPWindow through
2428 * |HandleEvent| to tell the plugin when its window moved
2430 gfxContext
*ctx
= aRenderingContext
.ThebesContext();
2432 gfxMatrix ctxMatrix
= ctx
->CurrentMatrix();
2433 if (ctxMatrix
.HasNonTranslation()) {
2434 // soo; in the future, we should be able to render
2435 // the object content to an offscreen DC, and then
2436 // composite it in with the right transforms.
2438 // But, we don't bother doing that, because we don't
2439 // have the event handling story figured out yet.
2440 // Instead, let's just bail.
2445 origin
.x
= NSToIntRound(float(ctxMatrix
.GetTranslation().x
));
2446 origin
.y
= NSToIntRound(float(ctxMatrix
.GetTranslation().y
));
2448 /* Need to force the clip to be set */
2449 ctx
->UpdateSurfaceClip();
2451 /* Set the device offsets as appropriate, for whatever our current group offsets might be */
2452 gfxFloat xoff
, yoff
;
2453 nsRefPtr
<gfxASurface
> surf
= ctx
->CurrentSurface(&xoff
, &yoff
);
2455 if (surf
->CairoStatus() != 0) {
2456 NS_WARNING("Plugin is being asked to render to a surface that's in error!");
2460 // check if we need to update the PS
2461 HPS hps
= (HPS
)aRenderingContext
.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS
);
2462 if (reinterpret_cast<HPS
>(window
->window
) != hps
) {
2463 window
->window
= reinterpret_cast<void*>(hps
);
2464 doupdatewindow
= PR_TRUE
;
2466 LONG lPSid
= GpiSavePS(hps
);
2468 if (GpiQueryDevice(hps
) != NULLHANDLE
) { // ensure that we have an associated HDC
2469 if (GpiQueryPageViewport(hps
, &rclViewport
)) {
2470 rclViewport
.xLeft
+= (LONG
)xoff
;
2471 rclViewport
.xRight
+= (LONG
)xoff
;
2472 rclViewport
.yBottom
+= (LONG
)yoff
;
2473 rclViewport
.yTop
+= (LONG
)yoff
;
2474 GpiSetPageViewport(hps
, &rclViewport
);
2478 if ((window
->x
!= origin
.x
) || (window
->y
!= origin
.y
)) {
2479 window
->x
= origin
.x
;
2480 window
->y
= origin
.y
;
2481 doupdatewindow
= PR_TRUE
;
2484 // if our location or visible area has changed, we need to tell the plugin
2485 if (doupdatewindow
) {
2486 inst
->SetWindow(window
);
2489 mInstanceOwner
->Paint(aDirtyRect
, hps
);
2491 GpiRestorePS(hps
, lPSid
);
2500 nsObjectFrame::HandleEvent(nsPresContext
* aPresContext
,
2501 nsGUIEvent
* anEvent
,
2502 nsEventStatus
* anEventStatus
)
2504 NS_ENSURE_ARG_POINTER(anEvent
);
2505 NS_ENSURE_ARG_POINTER(anEventStatus
);
2506 nsresult rv
= NS_OK
;
2508 if (!mInstanceOwner
)
2509 return NS_ERROR_NULL_POINTER
;
2511 mInstanceOwner
->ConsiderNewEventloopNestingLevel();
2513 if (anEvent
->message
== NS_PLUGIN_ACTIVATE
) {
2514 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
2515 nsCOMPtr
<nsIDOMElement
> elem
= do_QueryInterface(GetContent());
2517 return fm
->SetFocus(elem
, 0);
2519 else if (anEvent
->message
== NS_PLUGIN_FOCUS
) {
2520 nsIFocusManager_MOZILLA_2_0_BRANCH
* fm
= nsFocusManager::GetFocusManager();
2522 return fm
->FocusPlugin(GetContent());
2525 if (mInstanceOwner
->SendNativeEvents() &&
2526 (NS_IS_PLUGIN_EVENT(anEvent
) || NS_IS_NON_RETARGETED_PLUGIN_EVENT(anEvent
))) {
2527 *anEventStatus
= mInstanceOwner
->ProcessEvent(*anEvent
);
2532 rv
= nsObjectFrameSuper::HandleEvent(aPresContext
, anEvent
, anEventStatus
);
2537 // we want to process some native mouse events in the cocoa event model
2538 if ((anEvent
->message
== NS_MOUSE_ENTER
|| anEvent
->message
== NS_MOUSE_SCROLL
) &&
2539 mInstanceOwner
->GetEventModel() == NPEventModelCocoa
) {
2540 *anEventStatus
= mInstanceOwner
->ProcessEvent(*anEvent
);
2545 if (anEvent
->message
== NS_DESTROY
) {
2546 #ifdef MAC_CARBON_PLUGINS
2547 mInstanceOwner
->CancelTimer();
2552 return nsObjectFrameSuper::HandleEvent(aPresContext
, anEvent
, anEventStatus
);
2556 // Needed to make the routing of mouse events while dragging conform to
2557 // standard OS X practice, and to the Cocoa NPAPI spec. See bug 525078.
2559 nsObjectFrame::HandlePress(nsPresContext
* aPresContext
,
2560 nsGUIEvent
* anEvent
,
2561 nsEventStatus
* anEventStatus
)
2563 nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED
);
2564 return nsObjectFrameSuper::HandlePress(aPresContext
, anEvent
, anEventStatus
);
2569 nsObjectFrame::GetPluginInstance(nsIPluginInstance
*& aPluginInstance
)
2571 aPluginInstance
= nsnull
;
2573 if (!mInstanceOwner
)
2576 return mInstanceOwner
->GetInstance(aPluginInstance
);
2580 nsObjectFrame::PrepareInstanceOwner()
2582 nsWeakFrame
weakFrame(this);
2584 // First, have to stop any possibly running plugins.
2585 StopPluginInternal(PR_FALSE
);
2587 if (!weakFrame
.IsAlive()) {
2588 return NS_ERROR_NOT_AVAILABLE
;
2591 NS_ASSERTION(!mInstanceOwner
, "Must not have an instance owner here");
2593 mInstanceOwner
= new nsPluginInstanceOwner();
2595 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
2596 ("Created new instance owner %p for frame %p\n", mInstanceOwner
.get(),
2599 if (!mInstanceOwner
)
2600 return NS_ERROR_OUT_OF_MEMORY
;
2602 // Note, |this| may very well be gone after this call.
2603 return mInstanceOwner
->Init(PresContext(), this, GetContent());
2607 nsObjectFrame::Instantiate(nsIChannel
* aChannel
, nsIStreamListener
** aStreamListener
)
2609 if (mPreventInstantiation
) {
2613 // Note: If PrepareInstanceOwner() returns an error, |this| may very
2614 // well be deleted already.
2615 nsresult rv
= PrepareInstanceOwner();
2616 NS_ENSURE_SUCCESS(rv
, rv
);
2618 nsCOMPtr
<nsIPluginHost
> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
, &rv
));
2621 mInstanceOwner
->SetPluginHost(pluginHost
);
2623 // This must be done before instantiating the plugin
2624 FixupWindow(GetContentRect().Size());
2626 // Ensure we redraw when a plugin is instantiated
2627 Invalidate(GetContentRect() - GetPosition());
2629 nsWeakFrame
weakFrame(this);
2631 NS_ASSERTION(!mPreventInstantiation
, "Say what?");
2632 mPreventInstantiation
= PR_TRUE
;
2633 rv
= pluginHost
->InstantiatePluginForChannel(aChannel
, mInstanceOwner
, aStreamListener
);
2635 if (!weakFrame
.IsAlive()) {
2636 return NS_ERROR_NOT_AVAILABLE
;
2639 NS_ASSERTION(mPreventInstantiation
,
2640 "Instantiation should still be prevented!");
2641 mPreventInstantiation
= PR_FALSE
;
2643 #ifdef ACCESSIBILITY
2644 nsAccessibilityService
* accService
= nsIPresShell::AccService();
2646 accService
->RecreateAccessible(PresContext()->PresShell(), mContent
);
2654 nsObjectFrame::Instantiate(const char* aMimeType
, nsIURI
* aURI
)
2656 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
2657 ("nsObjectFrame::Instantiate(%s) called on frame %p\n", aMimeType
,
2660 if (mPreventInstantiation
) {
2664 // XXXbz can aMimeType ever actually be null here? If not, either
2665 // the callers are wrong (and passing "" instead of null) or we can
2666 // remove the codepaths dealing with null aMimeType in
2667 // InstantiateEmbeddedPlugin.
2668 NS_ASSERTION(aMimeType
|| aURI
, "Need a type or a URI!");
2670 // Note: If PrepareInstanceOwner() returns an error, |this| may very
2671 // well be deleted already.
2672 nsresult rv
= PrepareInstanceOwner();
2673 NS_ENSURE_SUCCESS(rv
, rv
);
2675 nsWeakFrame
weakFrame(this);
2677 // This must be done before instantiating the plugin
2678 FixupWindow(GetContentRect().Size());
2680 // Ensure we redraw when a plugin is instantiated
2681 Invalidate(GetContentRect() - GetPosition());
2683 // get the nsIPluginHost service
2684 nsCOMPtr
<nsIPluginHost
> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
, &rv
));
2687 mInstanceOwner
->SetPluginHost(pluginHost
);
2689 NS_ASSERTION(!mPreventInstantiation
, "Say what?");
2690 mPreventInstantiation
= PR_TRUE
;
2692 rv
= InstantiatePlugin(pluginHost
, aMimeType
, aURI
);
2694 if (!weakFrame
.IsAlive()) {
2695 return NS_ERROR_NOT_AVAILABLE
;
2699 if (NS_SUCCEEDED(rv
)) {
2700 TryNotifyContentObjectWrapper();
2702 if (!weakFrame
.IsAlive()) {
2703 return NS_ERROR_NOT_AVAILABLE
;
2709 NS_ASSERTION(mPreventInstantiation
,
2710 "Instantiation should still be prevented!");
2712 #ifdef ACCESSIBILITY
2713 nsAccessibilityService
* accService
= nsIPresShell::AccService();
2715 accService
->RecreateAccessible(PresContext()->PresShell(), mContent
);
2719 mPreventInstantiation
= PR_FALSE
;
2725 nsObjectFrame::TryNotifyContentObjectWrapper()
2727 nsCOMPtr
<nsIPluginInstance
> inst
;
2728 mInstanceOwner
->GetInstance(*getter_AddRefs(inst
));
2730 // The plugin may have set up new interfaces; we need to mess with our JS
2731 // wrapper. Note that we DO NOT want to call this if there is no plugin
2732 // instance! That would just reenter Instantiate(), trying to create
2733 // said plugin instance.
2734 NotifyContentObjectWrapper();
2738 class nsStopPluginRunnable
: public nsRunnable
, public nsITimerCallback
2741 NS_DECL_ISUPPORTS_INHERITED
2743 nsStopPluginRunnable(nsPluginInstanceOwner
*aInstanceOwner
)
2744 : mInstanceOwner(aInstanceOwner
)
2746 NS_ASSERTION(aInstanceOwner
, "need an owner");
2753 NS_IMETHOD
Notify(nsITimer
*timer
);
2756 nsCOMPtr
<nsITimer
> mTimer
;
2757 nsRefPtr
<nsPluginInstanceOwner
> mInstanceOwner
;
2760 NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable
, nsRunnable
, nsITimerCallback
)
2763 GetMIMEType(nsIPluginInstance
*aPluginInstance
)
2765 if (aPluginInstance
) {
2766 const char* mime
= nsnull
;
2767 if (NS_SUCCEEDED(aPluginInstance
->GetMIMEType(&mime
)) && mime
)
2774 DoDelayedStop(nsPluginInstanceOwner
*aInstanceOwner
, PRBool aDelayedStop
)
2776 #if (MOZ_PLATFORM_MAEMO==5)
2777 // Don't delay stop on Maemo/Hildon (bug 530739).
2778 if (aDelayedStop
&& aInstanceOwner
->MatchPluginName("Shockwave Flash"))
2782 // Don't delay stopping QuickTime (bug 425157), Flip4Mac (bug 426524),
2783 // XStandard (bug 430219), CMISS Zinc (bug 429604).
2785 #if !(defined XP_WIN || defined MOZ_X11)
2786 && !aInstanceOwner
->MatchPluginName("QuickTime")
2787 && !aInstanceOwner
->MatchPluginName("Flip4Mac")
2788 && !aInstanceOwner
->MatchPluginName("XStandard plugin")
2789 && !aInstanceOwner
->MatchPluginName("CMISS Zinc Plugin")
2792 nsCOMPtr
<nsIRunnable
> evt
= new nsStopPluginRunnable(aInstanceOwner
);
2793 NS_DispatchToCurrentThread(evt
);
2800 DoStopPlugin(nsPluginInstanceOwner
*aInstanceOwner
, PRBool aDelayedStop
)
2802 nsCOMPtr
<nsIPluginInstance
> inst
;
2803 aInstanceOwner
->GetInstance(*getter_AddRefs(inst
));
2806 aInstanceOwner
->GetWindow(win
);
2807 nsPluginNativeWindow
*window
= (nsPluginNativeWindow
*)win
;
2808 nsCOMPtr
<nsIPluginInstance
> nullinst
;
2811 window
->CallSetWindow(nullinst
);
2813 inst
->SetWindow(nsnull
);
2815 if (DoDelayedStop(aInstanceOwner
, aDelayedStop
))
2818 #if defined(XP_MACOSX)
2819 aInstanceOwner
->HidePluginWindow();
2822 nsCOMPtr
<nsIPluginHost
> pluginHost
= do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
);
2823 NS_ASSERTION(pluginHost
, "Without a pluginHost, how can we have an instance to destroy?");
2824 pluginHost
->StopPluginInstance(inst
);
2826 // the frame is going away along with its widget so tell the
2827 // window to forget its widget too
2829 window
->SetPluginWidget(nsnull
);
2832 aInstanceOwner
->Destroy();
2836 nsStopPluginRunnable::Notify(nsITimer
*aTimer
)
2842 nsStopPluginRunnable::Run()
2844 // InitWithCallback calls Release before AddRef so we need to hold a
2845 // strong ref on 'this' since we fall through to this scope if it fails.
2846 nsCOMPtr
<nsITimerCallback
> kungFuDeathGrip
= this;
2847 nsCOMPtr
<nsIAppShell
> appShell
= do_GetService(kAppShellCID
);
2849 PRUint32 currentLevel
= 0;
2850 appShell
->GetEventloopNestingLevel(¤tLevel
);
2851 if (currentLevel
> mInstanceOwner
->GetLastEventloopNestingLevel()) {
2853 mTimer
= do_CreateInstance("@mozilla.org/timer;1");
2855 // Fire 100ms timer to try to tear down this plugin as quickly as
2856 // possible once the nesting level comes back down.
2857 nsresult rv
= mTimer
->InitWithCallback(this, 100, nsITimer::TYPE_ONE_SHOT
);
2858 if (NS_SUCCEEDED(rv
)) {
2862 NS_ERROR("Failed to setup a timer to stop the plugin later (at a safe "
2863 "time). Stopping the plugin now, this might crash.");
2869 DoStopPlugin(mInstanceOwner
, PR_FALSE
);
2875 nsObjectFrame::StopPlugin()
2877 PRBool delayedStop
= PR_FALSE
;
2879 nsCOMPtr
<nsIPluginInstance
> inst
;
2881 mInstanceOwner
->GetInstance(*getter_AddRefs(inst
));
2883 // Delayed stop for Real plugin only; see bug 420886, 426852.
2884 const char* pluginType
= ::GetMIMEType(inst
);
2885 delayedStop
= strcmp(pluginType
, "audio/x-pn-realaudio-plugin") == 0;
2888 StopPluginInternal(delayedStop
);
2892 nsObjectFrame::StopPluginInternal(PRBool aDelayedStop
)
2894 if (!mInstanceOwner
) {
2898 nsRootPresContext
* rpc
= PresContext()->GetRootPresContext();
2900 NS_ASSERTION(PresContext()->PresShell()->IsFrozen(),
2901 "unable to unregister the plugin frame");
2904 rpc
->UnregisterPluginForGeometryUpdates(this);
2906 // Make sure the plugin is hidden in case an update of plugin geometry
2907 // hasn't happened since this plugin became hidden.
2908 nsIWidget
* parent
= mWidget
->GetParent();
2910 nsTArray
<nsIWidget::Configuration
> configurations
;
2911 GetEmptyClipConfiguration(&configurations
);
2912 parent
->ConfigureChildren(configurations
);
2917 rpc
->UnregisterPluginForGeometryUpdates(this);
2921 // Transfer the reference to the instance owner onto the stack so
2922 // that if we do end up re-entering this code, or if we unwind back
2923 // here witha deleted frame (this), we can still continue to stop
2924 // the plugin. Note that due to that, the ordering of the code in
2925 // this function is extremely important.
2927 nsRefPtr
<nsPluginInstanceOwner
> owner
;
2928 owner
.swap(mInstanceOwner
);
2930 // Make sure that our windowless rect has been zeroed out, so if we
2931 // get reinstantiated we'll send the right messages to the plug-in.
2932 mWindowlessRect
.Empty();
2934 PRBool oldVal
= mPreventInstantiation
;
2935 mPreventInstantiation
= PR_TRUE
;
2937 nsWeakFrame
weakFrame(this);
2939 #if defined(XP_WIN) || defined(MOZ_X11)
2940 if (aDelayedStop
&& mWidget
) {
2941 // If we're asked to do a delayed stop it means we're stopping the
2942 // plugin because we're destroying the frame. In that case, disown
2944 mInnerView
->DetachWidgetEventHandler(mWidget
);
2949 // From this point on, |this| could have been deleted, so don't
2951 owner
->PrepareToStop(aDelayedStop
);
2953 DoStopPlugin(owner
, aDelayedStop
);
2955 // If |this| is still alive, reset mPreventInstantiation.
2956 if (weakFrame
.IsAlive()) {
2957 NS_ASSERTION(mPreventInstantiation
,
2958 "Instantiation should still be prevented!");
2960 mPreventInstantiation
= oldVal
;
2963 // Break relationship between frame and plugin instance owner
2964 owner
->SetOwner(nsnull
);
2968 nsObjectFrame::NotifyContentObjectWrapper()
2970 nsCOMPtr
<nsIDocument
> doc
= mContent
->GetDocument();
2974 nsIScriptGlobalObject
*sgo
= doc
->GetScriptGlobalObject();
2978 nsIScriptContext
*scx
= sgo
->GetContext();
2982 JSContext
*cx
= (JSContext
*)scx
->GetNativeContext();
2984 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
2985 nsContentUtils::XPConnect()->
2986 GetWrappedNativeOfNativeObject(cx
, sgo
->GetGlobalJSObject(), mContent
,
2987 NS_GET_IID(nsISupports
),
2988 getter_AddRefs(wrapper
));
2991 // Nothing to do here if there's no wrapper for mContent. The proto
2992 // chain will be fixed appropriately when the wrapper is created.
2996 JSObject
*obj
= nsnull
;
2997 nsresult rv
= wrapper
->GetJSObject(&obj
);
3001 nsHTMLPluginObjElementSH::SetupProtoChain(wrapper
, cx
, obj
);
3006 nsObjectFrame::GetNextObjectFrame(nsPresContext
* aPresContext
, nsIFrame
* aRoot
)
3008 nsIFrame
* child
= aRoot
->GetFirstChild(nsnull
);
3011 nsIObjectFrame
* outFrame
= do_QueryFrame(child
);
3013 nsCOMPtr
<nsIPluginInstance
> pi
;
3014 outFrame
->GetPluginInstance(*getter_AddRefs(pi
)); // make sure we have a REAL plugin
3019 outFrame
= GetNextObjectFrame(aPresContext
, child
);
3022 child
= child
->GetNextSibling();
3029 nsObjectFrame::BeginSwapDocShells(nsIContent
* aContent
, void*)
3031 NS_PRECONDITION(aContent
, "");
3033 // This function is called from a document content enumerator so we need
3034 // to filter out the nsObjectFrames and ignore the rest.
3035 nsIObjectFrame
* obj
= do_QueryFrame(aContent
->GetPrimaryFrame());
3039 nsObjectFrame
* objectFrame
= static_cast<nsObjectFrame
*>(obj
);
3040 NS_ASSERTION(!objectFrame
->mWidget
|| objectFrame
->mWidget
->GetParent(),
3041 "Plugin windows must not be toplevel");
3042 nsRootPresContext
* rootPC
= objectFrame
->PresContext()->GetRootPresContext();
3043 NS_ASSERTION(rootPC
, "unable to unregister the plugin frame");
3044 rootPC
->UnregisterPluginForGeometryUpdates(objectFrame
);
3048 nsObjectFrame::EndSwapDocShells(nsIContent
* aContent
, void*)
3050 NS_PRECONDITION(aContent
, "");
3052 // This function is called from a document content enumerator so we need
3053 // to filter out the nsObjectFrames and ignore the rest.
3054 nsIObjectFrame
* obj
= do_QueryFrame(aContent
->GetPrimaryFrame());
3058 nsObjectFrame
* objectFrame
= static_cast<nsObjectFrame
*>(obj
);
3059 nsRootPresContext
* rootPC
= objectFrame
->PresContext()->GetRootPresContext();
3060 NS_ASSERTION(rootPC
, "unable to register the plugin frame");
3061 nsIWidget
* widget
= objectFrame
->GetWidget();
3063 // Reparent the widget.
3065 rootPC
->PresShell()->GetRootFrame()->GetNearestWidget();
3066 widget
->SetParent(parent
);
3067 objectFrame
->CallSetWindow();
3069 // Register for geometry updates and make a request.
3070 rootPC
->RegisterPluginForGeometryUpdates(objectFrame
);
3071 rootPC
->RequestUpdatePluginGeometry(objectFrame
);
3076 NS_NewObjectFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
3078 return new (aPresShell
) nsObjectFrame(aContext
);
3081 NS_IMPL_FRAMEARENA_HELPERS(nsObjectFrame
)
3084 // nsPluginDOMContextMenuListener class implementation
3086 nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener()
3090 nsPluginDOMContextMenuListener::~nsPluginDOMContextMenuListener()
3094 NS_IMPL_ISUPPORTS2(nsPluginDOMContextMenuListener
,
3095 nsIDOMContextMenuListener
,
3096 nsIDOMEventListener
)
3099 nsPluginDOMContextMenuListener::ContextMenu(nsIDOMEvent
* aContextMenuEvent
)
3101 aContextMenuEvent
->PreventDefault(); // consume event
3106 nsresult
nsPluginDOMContextMenuListener::Init(nsIContent
* aContent
)
3108 nsCOMPtr
<nsIDOMEventTarget
> receiver(do_QueryInterface(aContent
));
3110 receiver
->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, PR_TRUE
);
3114 return NS_ERROR_NO_INTERFACE
;
3117 nsresult
nsPluginDOMContextMenuListener::Destroy(nsIContent
* aContent
)
3119 // Unregister context menu listener
3120 nsCOMPtr
<nsIDOMEventTarget
> receiver(do_QueryInterface(aContent
));
3122 receiver
->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, PR_TRUE
);
3128 //plugin instance owner
3130 nsPluginInstanceOwner::nsPluginInstanceOwner()
3132 // create nsPluginNativeWindow object, it is derived from NPWindow
3133 // struct and allows to manipulate native window procedure
3134 nsCOMPtr
<nsIPluginHost
> ph
= do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
);
3136 ph
->NewPluginNativeWindow(&mPluginWindow
);
3138 mPluginWindow
= nsnull
;
3140 mObjectFrame
= nsnull
;
3143 memset(&mCGPluginPortCopy
, 0, sizeof(NP_CGContext
));
3144 #ifndef NP_NO_QUICKDRAW
3145 memset(&mQDPluginPortCopy
, 0, sizeof(NP_Port
));
3147 mInCGPaintLevel
= 0;
3148 mSentInitialTopLevelWindowEvent
= PR_FALSE
;
3149 mIOSurface
= nsnull
;
3150 mPluginPortChanged
= PR_FALSE
;
3152 mContentFocused
= PR_FALSE
;
3153 mWidgetVisible
= PR_TRUE
;
3154 mPluginWindowVisible
= PR_FALSE
;
3155 mNumCachedAttrs
= 0;
3156 mNumCachedParams
= 0;
3157 mCachedAttrParamNames
= nsnull
;
3158 mCachedAttrParamValues
= nsnull
;
3159 mDestroyWidget
= PR_FALSE
;
3161 #ifdef MOZ_COMPOSITED_PLUGINS
3162 mLastPoint
= nsIntPoint(0,0);
3165 #ifdef MOZ_USE_IMAGE_EXPOSE
3166 mPluginSize
= nsIntSize(0,0);
3168 mBlitWindow
= nsnull
;
3169 mSharedXImage
= nsnull
;
3170 mSharedSegmentInfo
.shmaddr
= nsnull
;
3174 #ifndef NP_NO_QUICKDRAW
3175 mEventModel
= NPEventModelCarbon
;
3177 mEventModel
= NPEventModelCocoa
;
3181 mWaitingForPaint
= PR_FALSE
;
3183 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
3184 ("nsPluginInstanceOwner %p created\n", this));
3187 nsPluginInstanceOwner::~nsPluginInstanceOwner()
3191 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
3192 ("nsPluginInstanceOwner %p deleted\n", this));
3194 if (mWaitingForPaint
) {
3195 // We don't care when the event is dispatched as long as it's "soon",
3196 // since whoever needs it will be wwaiting for it
3197 nsCOMPtr
<nsIRunnable
> event
= new AsyncPaintWaitEvent(mContent
, PR_TRUE
);
3198 NS_DispatchToMainThread(event
);
3201 #ifdef MAC_CARBON_PLUGINS
3205 mObjectFrame
= nsnull
;
3207 for (cnt
= 0; cnt
< (mNumCachedAttrs
+ 1 + mNumCachedParams
); cnt
++) {
3208 if (mCachedAttrParamNames
&& mCachedAttrParamNames
[cnt
]) {
3209 NS_Free(mCachedAttrParamNames
[cnt
]);
3210 mCachedAttrParamNames
[cnt
] = nsnull
;
3213 if (mCachedAttrParamValues
&& mCachedAttrParamValues
[cnt
]) {
3214 NS_Free(mCachedAttrParamValues
[cnt
]);
3215 mCachedAttrParamValues
[cnt
] = nsnull
;
3219 if (mCachedAttrParamNames
) {
3220 NS_Free(mCachedAttrParamNames
);
3221 mCachedAttrParamNames
= nsnull
;
3224 if (mCachedAttrParamValues
) {
3225 NS_Free(mCachedAttrParamValues
);
3226 mCachedAttrParamValues
= nsnull
;
3234 // clean up plugin native window object
3235 nsCOMPtr
<nsIPluginHost
> ph
= do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
);
3237 ph
->DeletePluginNativeWindow(mPluginWindow
);
3238 mPluginWindow
= nsnull
;
3242 mInstance
->InvalidateOwner();
3245 #ifdef MOZ_USE_IMAGE_EXPOSE
3251 * nsISupports Implementation
3254 NS_IMPL_ADDREF(nsPluginInstanceOwner
)
3255 NS_IMPL_RELEASE(nsPluginInstanceOwner
)
3257 NS_INTERFACE_MAP_BEGIN(nsPluginInstanceOwner
)
3258 NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner
)
3259 NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner_MOZILLA_2_0_BRANCH
)
3260 NS_INTERFACE_MAP_ENTRY(nsIPluginTagInfo
)
3261 NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener
)
3262 NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener
)
3263 NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener
)
3264 NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener
)
3265 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener
, nsIDOMMouseListener
)
3266 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIPluginInstanceOwner
)
3267 NS_INTERFACE_MAP_END
3270 nsPluginInstanceOwner::SetInstance(nsIPluginInstance
*aInstance
)
3272 NS_ASSERTION(!mInstance
|| !aInstance
, "mInstance should only be set or unset!");
3274 // If we're going to null out mInstance after use, be sure to call
3275 // mInstance->InvalidateOwner() here, since it now won't be called
3276 // from our destructor. This fixes bug 613376.
3277 if (mInstance
&& !aInstance
)
3278 mInstance
->InvalidateOwner();
3280 mInstance
= aInstance
;
3285 NS_IMETHODIMP
nsPluginInstanceOwner::GetWindow(NPWindow
*&aWindow
)
3287 NS_ASSERTION(mPluginWindow
, "the plugin window object being returned is null");
3288 aWindow
= mPluginWindow
;
3292 NS_IMETHODIMP
nsPluginInstanceOwner::GetMode(PRInt32
*aMode
)
3294 nsCOMPtr
<nsIDocument
> doc
;
3295 nsresult rv
= GetDocument(getter_AddRefs(doc
));
3296 nsCOMPtr
<nsIPluginDocument
> pDoc (do_QueryInterface(doc
));
3307 NS_IMETHODIMP
nsPluginInstanceOwner::GetAttributes(PRUint16
& n
,
3308 const char*const*& names
,
3309 const char*const*& values
)
3311 nsresult rv
= EnsureCachedAttrParamArrays();
3312 NS_ENSURE_SUCCESS(rv
, rv
);
3314 n
= mNumCachedAttrs
;
3315 names
= (const char **)mCachedAttrParamNames
;
3316 values
= (const char **)mCachedAttrParamValues
;
3321 NS_IMETHODIMP
nsPluginInstanceOwner::GetAttribute(const char* name
, const char* *result
)
3323 NS_ENSURE_ARG_POINTER(name
);
3324 NS_ENSURE_ARG_POINTER(result
);
3326 nsresult rv
= EnsureCachedAttrParamArrays();
3327 NS_ENSURE_SUCCESS(rv
, rv
);
3331 for (int i
= 0; i
< mNumCachedAttrs
; i
++) {
3332 if (0 == PL_strcasecmp(mCachedAttrParamNames
[i
], name
)) {
3333 *result
= mCachedAttrParamValues
[i
];
3338 return NS_ERROR_FAILURE
;
3341 NS_IMETHODIMP
nsPluginInstanceOwner::GetDOMElement(nsIDOMElement
* *result
)
3343 return CallQueryInterface(mContent
, result
);
3346 NS_IMETHODIMP
nsPluginInstanceOwner::GetInstance(nsIPluginInstance
*&aInstance
)
3348 NS_IF_ADDREF(aInstance
= mInstance
);
3353 NS_IMETHODIMP
nsPluginInstanceOwner::GetURL(const char *aURL
,
3354 const char *aTarget
,
3355 nsIInputStream
*aPostStream
,
3357 PRUint32 aHeadersDataLen
)
3359 NS_ENSURE_TRUE(mObjectFrame
, NS_ERROR_NULL_POINTER
);
3361 if (mContent
->IsEditable()) {
3365 // the container of the pres context will give us the link handler
3366 nsCOMPtr
<nsISupports
> container
= mObjectFrame
->PresContext()->GetContainer();
3367 NS_ENSURE_TRUE(container
,NS_ERROR_FAILURE
);
3368 nsCOMPtr
<nsILinkHandler
> lh
= do_QueryInterface(container
);
3369 NS_ENSURE_TRUE(lh
, NS_ERROR_FAILURE
);
3371 nsAutoString unitarget
;
3372 unitarget
.AssignASCII(aTarget
); // XXX could this be nonascii?
3374 nsCOMPtr
<nsIURI
> baseURI
= mContent
->GetBaseURI();
3376 // Create an absolute URL
3377 nsCOMPtr
<nsIURI
> uri
;
3378 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURL
, baseURI
);
3380 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
3382 nsCOMPtr
<nsIInputStream
> headersDataStream
;
3383 if (aPostStream
&& aHeadersData
) {
3384 if (!aHeadersDataLen
)
3385 return NS_ERROR_UNEXPECTED
;
3387 nsCOMPtr
<nsIStringInputStream
> sis
= do_CreateInstance("@mozilla.org/io/string-input-stream;1");
3389 return NS_ERROR_OUT_OF_MEMORY
;
3391 rv
= sis
->SetData((char *)aHeadersData
, aHeadersDataLen
);
3392 NS_ENSURE_SUCCESS(rv
, rv
);
3393 headersDataStream
= do_QueryInterface(sis
);
3396 PRInt32 blockPopups
=
3397 nsContentUtils::GetIntPref("privacy.popups.disable_from_plugins");
3398 nsAutoPopupStatePusher
popupStatePusher((PopupControlState
)blockPopups
);
3400 rv
= lh
->OnLinkClick(mContent
, uri
, unitarget
.get(),
3401 aPostStream
, headersDataStream
);
3406 NS_IMETHODIMP
nsPluginInstanceOwner::ShowStatus(const char *aStatusMsg
)
3408 nsresult rv
= NS_ERROR_FAILURE
;
3410 rv
= this->ShowStatus(NS_ConvertUTF8toUTF16(aStatusMsg
).get());
3415 NS_IMETHODIMP
nsPluginInstanceOwner::ShowStatus(const PRUnichar
*aStatusMsg
)
3417 nsresult rv
= NS_ERROR_FAILURE
;
3419 if (!mObjectFrame
) {
3422 nsCOMPtr
<nsISupports
> cont
= mObjectFrame
->PresContext()->GetContainer();
3427 nsCOMPtr
<nsIDocShellTreeItem
> docShellItem(do_QueryInterface(cont
, &rv
));
3428 if (NS_FAILED(rv
) || !docShellItem
) {
3432 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3433 rv
= docShellItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
3434 if (NS_FAILED(rv
) || !treeOwner
) {
3438 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome(do_GetInterface(treeOwner
, &rv
));
3439 if (NS_FAILED(rv
) || !browserChrome
) {
3442 rv
= browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT
,
3448 NS_IMETHODIMP
nsPluginInstanceOwner::GetDocument(nsIDocument
* *aDocument
)
3451 return NS_ERROR_NULL_POINTER
;
3453 // XXX sXBL/XBL2 issue: current doc or owner doc?
3454 // But keep in mind bug 322414 comment 33
3455 NS_IF_ADDREF(*aDocument
= mContent
->GetOwnerDoc());
3459 NS_IMETHODIMP
nsPluginInstanceOwner::InvalidateRect(NPRect
*invalidRect
)
3461 if (mWaitingForPaint
&& IsUpToDate()) {
3462 // We don't care when the event is dispatched as long as it's "soon",
3463 // since whoever needs it will be wwaiting for it
3464 nsCOMPtr
<nsIRunnable
> event
= new AsyncPaintWaitEvent(mContent
, PR_TRUE
);
3465 NS_DispatchToMainThread(event
);
3466 mWaitingForPaint
= false;
3469 if (!mObjectFrame
|| !invalidRect
|| !mWidgetVisible
)
3470 return NS_ERROR_FAILURE
;
3472 // Each time an asynchronously-drawing plugin sends a new surface to display,
3473 // InvalidateRect is called. We notify reftests that painting is up to
3474 // date and update our ImageContainer with the new surface.
3475 nsRefPtr
<ImageContainer
> container
= mObjectFrame
->GetImageContainer();
3477 SetCurrentImage(container
);
3480 #ifdef MOZ_USE_IMAGE_EXPOSE
3481 PRBool simpleImageRender
= PR_FALSE
;
3482 mInstance
->GetValueFromPlugin(NPPVpluginWindowlessLocalBool
,
3483 &simpleImageRender
);
3484 if (simpleImageRender
) {
3485 NativeImageDraw(invalidRect
);
3491 // Windowed plugins should not be calling NPN_InvalidateRect, but
3492 // Silverlight does and expects it to "work"
3494 mWidget
->Invalidate(nsIntRect(invalidRect
->left
, invalidRect
->top
,
3495 invalidRect
->right
- invalidRect
->left
,
3496 invalidRect
->bottom
- invalidRect
->top
),
3502 nsPresContext
* presContext
= mObjectFrame
->PresContext();
3503 nsRect
rect(presContext
->DevPixelsToAppUnits(invalidRect
->left
),
3504 presContext
->DevPixelsToAppUnits(invalidRect
->top
),
3505 presContext
->DevPixelsToAppUnits(invalidRect
->right
- invalidRect
->left
),
3506 presContext
->DevPixelsToAppUnits(invalidRect
->bottom
- invalidRect
->top
));
3508 mObjectFrame
->InvalidateLayer(rect
+ mObjectFrame
->GetUsedBorderAndPadding().TopLeft(), nsDisplayItem::TYPE_PLUGIN
);
3510 if (mozilla::FrameLayerBuilder::HasDedicatedLayer(mObjectFrame
, nsDisplayItem::TYPE_PLUGIN
)) {
3511 mObjectFrame
->InvalidateWithFlags(rect
+ mObjectFrame
->GetUsedBorderAndPadding().TopLeft(),
3512 nsIFrame::INVALIDATE_NO_UPDATE_LAYER_TREE
);
3514 mObjectFrame
->Invalidate(rect
+ mObjectFrame
->GetUsedBorderAndPadding().TopLeft());
3520 NS_IMETHODIMP
nsPluginInstanceOwner::InvalidateRegion(NPRegion invalidRegion
)
3522 return NS_ERROR_NOT_IMPLEMENTED
;
3525 NS_IMETHODIMP
nsPluginInstanceOwner::ForceRedraw()
3527 NS_ENSURE_TRUE(mObjectFrame
, NS_ERROR_NULL_POINTER
);
3528 nsIView
* view
= mObjectFrame
->GetView();
3530 return view
->GetViewManager()->Composite();
3536 NS_IMETHODIMP
nsPluginInstanceOwner::GetNetscapeWindow(void *value
)
3538 if (!mObjectFrame
) {
3539 NS_WARNING("plugin owner has no owner in getting doc's window handle");
3540 return NS_ERROR_FAILURE
;
3543 #if defined(XP_WIN) || defined(XP_OS2)
3544 void** pvalue
= (void**)value
;
3545 nsIViewManager
* vm
= mObjectFrame
->PresContext()->GetPresShell()->GetViewManager();
3547 return NS_ERROR_FAILURE
;
3549 // This property is provided to allow a "windowless" plugin to determine the window it is drawing
3550 // in, so it can translate mouse coordinates it receives directly from the operating system
3551 // to coordinates relative to itself.
3553 // The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin
3554 // is drawing into has the same origin as the document's window, but this is not the case for "windowless" plugins inside of scrolling DIVs etc
3556 // To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code
3557 // determines the window handle of the mozilla window containing the "windowless" plugin.
3559 // Given that this HWND may not be that of the document's window, there is a slight risk
3560 // of confusing a plugin that is using this HWND for illicit purposes, but since the documentation
3561 // does not suggest this HWND IS that of the document window, rather that of the window
3562 // the plugin is drawn in, this seems like a safe fix.
3564 // we only attempt to get the nearest window if this really is a "windowless" plugin so as not
3565 // to change any behaviour for the much more common windowed plugins,
3566 // though why this method would even be being called for a windowed plugin escapes me.
3567 if (mPluginWindow
&& mPluginWindow
->type
== NPWindowTypeDrawable
) {
3568 // it turns out that flash also uses this window for determining focus, and is currently
3569 // unable to show a caret correctly if we return the enclosing window. Therefore for
3570 // now we only return the enclosing window when there is an actual offset which
3571 // would otherwise cause coordinates to be offset incorrectly. (i.e.
3572 // if the enclosing window if offset from the document window)
3574 // fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw
3575 // does not seem to be possible without a change to the flash plugin
3577 nsIWidget
* win
= mObjectFrame
->GetNearestWidget();
3579 nsIView
*view
= nsIView::GetViewFor(win
);
3580 NS_ASSERTION(view
, "No view for widget");
3581 nsPoint offset
= view
->GetOffsetTo(nsnull
);
3583 if (offset
.x
|| offset
.y
) {
3584 // in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
3585 // so that mouse co-ordinates are not messed up.
3586 *pvalue
= (void*)win
->GetNativeData(NS_NATIVE_WINDOW
);
3593 // simply return the topmost document window
3594 nsCOMPtr
<nsIWidget
> widget
;
3595 nsresult rv
= vm
->GetRootWidget(getter_AddRefs(widget
));
3597 *pvalue
= (void*)widget
->GetNativeData(NS_NATIVE_WINDOW
);
3599 NS_ASSERTION(widget
, "couldn't get doc's widget in getting doc's window handle");
3603 #elif defined(MOZ_WIDGET_GTK2)
3604 // X11 window managers want the toplevel window for WM_TRANSIENT_FOR.
3605 nsIWidget
* win
= mObjectFrame
->GetNearestWidget();
3607 return NS_ERROR_FAILURE
;
3608 GdkWindow
* gdkWindow
= static_cast<GdkWindow
*>(win
->GetNativeData(NS_NATIVE_WINDOW
));
3610 return NS_ERROR_FAILURE
;
3611 gdkWindow
= gdk_window_get_toplevel(gdkWindow
);
3613 *static_cast<Window
*>(value
) = GDK_WINDOW_XID(gdkWindow
);
3616 #elif defined(MOZ_WIDGET_QT)
3617 // X11 window managers want the toplevel window for WM_TRANSIENT_FOR.
3618 nsIWidget
* win
= mObjectFrame
->GetNearestWidget();
3620 return NS_ERROR_FAILURE
;
3621 QWidget
* widget
= static_cast<QWidget
*>(win
->GetNativeData(NS_NATIVE_WINDOW
));
3623 return NS_ERROR_FAILURE
;
3625 *static_cast<Window
*>(value
) = widget
->handle();
3628 return NS_ERROR_FAILURE
;
3630 return NS_ERROR_NOT_IMPLEMENTED
;
3634 NS_IMETHODIMP
nsPluginInstanceOwner::SetEventModel(PRInt32 eventModel
)
3637 mEventModel
= static_cast<NPEventModel
>(eventModel
);
3640 return NS_ERROR_NOT_IMPLEMENTED
;
3644 NS_IMETHODIMP
nsPluginInstanceOwner::SetWindow()
3646 NS_ENSURE_TRUE(mObjectFrame
, NS_ERROR_NULL_POINTER
);
3647 return mObjectFrame
->CallSetWindow(PR_FALSE
);
3650 NPError
nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu
* menu
, void* event
)
3652 if (!menu
|| !event
)
3653 return NPERR_GENERIC_ERROR
;
3656 if (GetEventModel() != NPEventModelCocoa
)
3657 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
3659 return NS_NPAPI_ShowCocoaContextMenu(static_cast<void*>(menu
), mWidget
,
3660 static_cast<NPCocoaEvent
*>(event
));
3662 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
3666 NPBool
nsPluginInstanceOwner::ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
3667 double *destX
, double *destY
, NPCoordinateSpace destSpace
)
3673 return NS_NPAPI_ConvertPointCocoa(mWidget
->GetNativeData(NS_NATIVE_WIDGET
),
3674 sourceX
, sourceY
, sourceSpace
, destX
, destY
, destSpace
);
3676 // we should implement this for all platforms
3681 NS_IMETHODIMP
nsPluginInstanceOwner::GetTagType(nsPluginTagType
*result
)
3683 NS_ENSURE_ARG_POINTER(result
);
3685 *result
= nsPluginTagType_Unknown
;
3687 nsIAtom
*atom
= mContent
->Tag();
3689 if (atom
== nsGkAtoms::applet
)
3690 *result
= nsPluginTagType_Applet
;
3691 else if (atom
== nsGkAtoms::embed
)
3692 *result
= nsPluginTagType_Embed
;
3693 else if (atom
== nsGkAtoms::object
)
3694 *result
= nsPluginTagType_Object
;
3699 NS_IMETHODIMP
nsPluginInstanceOwner::GetTagText(const char* *result
)
3701 NS_ENSURE_ARG_POINTER(result
);
3702 if (nsnull
== mTagText
) {
3704 nsCOMPtr
<nsIDOMNode
> node(do_QueryInterface(mContent
, &rv
));
3708 nsCOMPtr
<nsIDocument
> document
;
3709 rv
= GetDocument(getter_AddRefs(document
));
3713 nsCOMPtr
<nsIDOMDocument
> domDoc
= do_QueryInterface(document
);
3714 NS_ASSERTION(domDoc
, "Need a document");
3716 nsCOMPtr
<nsIDocumentEncoder
> docEncoder(do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE
"text/html", &rv
));
3719 rv
= docEncoder
->Init(domDoc
, NS_LITERAL_STRING("text/html"), nsIDocumentEncoder::OutputEncodeBasicEntities
);
3723 nsCOMPtr
<nsIDOMRange
> range(do_CreateInstance(kRangeCID
,&rv
));
3727 rv
= range
->SelectNode(node
);
3731 docEncoder
->SetRange(range
);
3732 nsString elementHTML
;
3733 rv
= docEncoder
->EncodeToString(elementHTML
);
3737 mTagText
= ToNewUTF8String(elementHTML
);
3739 return NS_ERROR_OUT_OF_MEMORY
;
3745 NS_IMETHODIMP
nsPluginInstanceOwner::GetParameters(PRUint16
& n
, const char*const*& names
, const char*const*& values
)
3747 nsresult rv
= EnsureCachedAttrParamArrays();
3748 NS_ENSURE_SUCCESS(rv
, rv
);
3750 n
= mNumCachedParams
;
3752 names
= (const char **)(mCachedAttrParamNames
+ mNumCachedAttrs
+ 1);
3753 values
= (const char **)(mCachedAttrParamValues
+ mNumCachedAttrs
+ 1);
3755 names
= values
= nsnull
;
3760 NS_IMETHODIMP
nsPluginInstanceOwner::GetParameter(const char* name
, const char* *result
)
3762 NS_ENSURE_ARG_POINTER(name
);
3763 NS_ENSURE_ARG_POINTER(result
);
3765 nsresult rv
= EnsureCachedAttrParamArrays();
3766 NS_ENSURE_SUCCESS(rv
, rv
);
3770 for (int i
= mNumCachedAttrs
+ 1; i
< (mNumCachedParams
+ 1 + mNumCachedAttrs
); i
++) {
3771 if (0 == PL_strcasecmp(mCachedAttrParamNames
[i
], name
)) {
3772 *result
= mCachedAttrParamValues
[i
];
3777 return NS_ERROR_FAILURE
;
3780 NS_IMETHODIMP
nsPluginInstanceOwner::GetDocumentBase(const char* *result
)
3782 NS_ENSURE_ARG_POINTER(result
);
3783 nsresult rv
= NS_OK
;
3784 if (mDocumentBase
.IsEmpty()) {
3785 if (!mObjectFrame
) {
3787 return NS_ERROR_FAILURE
;
3790 nsIDocument
* doc
= mContent
->GetOwnerDoc();
3791 NS_ASSERTION(doc
, "Must have an owner doc");
3792 rv
= doc
->GetDocBaseURI()->GetSpec(mDocumentBase
);
3794 if (NS_SUCCEEDED(rv
))
3795 *result
= ToNewCString(mDocumentBase
);
3799 static nsDataHashtable
<nsDepCharHashKey
, const char *> * gCharsetMap
;
3805 /* XXX If you add any strings longer than
3806 * {"x-mac-cyrillic", "MacCyrillic"},
3807 * {"x-mac-ukrainian", "MacUkraine"},
3808 * to the following array then you MUST update the
3809 * sizes of the arrays in the moz2javaCharset struct
3812 static const moz2javaCharset charsets
[] =
3814 {"windows-1252", "Cp1252"},
3815 {"IBM850", "Cp850"},
3816 {"IBM852", "Cp852"},
3817 {"IBM855", "Cp855"},
3818 {"IBM857", "Cp857"},
3819 {"IBM828", "Cp862"},
3820 {"IBM864", "Cp864"},
3821 {"IBM866", "Cp866"},
3822 {"windows-1250", "Cp1250"},
3823 {"windows-1251", "Cp1251"},
3824 {"windows-1253", "Cp1253"},
3825 {"windows-1254", "Cp1254"},
3826 {"windows-1255", "Cp1255"},
3827 {"windows-1256", "Cp1256"},
3828 {"windows-1257", "Cp1257"},
3829 {"windows-1258", "Cp1258"},
3830 {"EUC-JP", "EUC_JP"},
3831 {"EUC-KR", "EUC_KR"},
3832 {"x-euc-tw", "EUC_TW"},
3833 {"gb18030", "GB18030"},
3835 {"ISO-2022-JP", "ISO2022JP"},
3836 {"ISO-2022-KR", "ISO2022KR"},
3837 {"ISO-8859-2", "ISO8859_2"},
3838 {"ISO-8859-3", "ISO8859_3"},
3839 {"ISO-8859-4", "ISO8859_4"},
3840 {"ISO-8859-5", "ISO8859_5"},
3841 {"ISO-8859-6", "ISO8859_6"},
3842 {"ISO-8859-7", "ISO8859_7"},
3843 {"ISO-8859-8", "ISO8859_8"},
3844 {"ISO-8859-9", "ISO8859_9"},
3845 {"ISO-8859-13", "ISO8859_13"},
3846 {"x-johab", "Johab"},
3847 {"KOI8-R", "KOI8_R"},
3848 {"TIS-620", "MS874"},
3849 {"windows-936", "MS936"},
3850 {"x-windows-949", "MS949"},
3851 {"x-mac-arabic", "MacArabic"},
3852 {"x-mac-croatian", "MacCroatia"},
3853 {"x-mac-cyrillic", "MacCyrillic"},
3854 {"x-mac-greek", "MacGreek"},
3855 {"x-mac-hebrew", "MacHebrew"},
3856 {"x-mac-icelandic", "MacIceland"},
3857 {"x-mac-roman", "MacRoman"},
3858 {"x-mac-romanian", "MacRomania"},
3859 {"x-mac-ukrainian", "MacUkraine"},
3860 {"Shift_JIS", "SJIS"},
3861 {"TIS-620", "TIS620"}
3864 NS_IMETHODIMP
nsPluginInstanceOwner::GetDocumentEncoding(const char* *result
)
3866 NS_ENSURE_ARG_POINTER(result
);
3870 // XXX sXBL/XBL2 issue: current doc or owner doc?
3871 nsCOMPtr
<nsIDocument
> doc
;
3872 rv
= GetDocument(getter_AddRefs(doc
));
3873 NS_ASSERTION(NS_SUCCEEDED(rv
), "failed to get document");
3877 const nsCString
&charset
= doc
->GetDocumentCharacterSet();
3879 if (charset
.IsEmpty())
3882 // common charsets and those not requiring conversion first
3883 if (charset
.EqualsLiteral("us-ascii")) {
3884 *result
= PL_strdup("US_ASCII");
3885 } else if (charset
.EqualsLiteral("ISO-8859-1") ||
3886 !nsCRT::strncmp(PromiseFlatCString(charset
).get(), "UTF", 3)) {
3887 *result
= ToNewCString(charset
);
3890 const int NUM_CHARSETS
= sizeof(charsets
) / sizeof(moz2javaCharset
);
3891 gCharsetMap
= new nsDataHashtable
<nsDepCharHashKey
, const char*>();
3892 if (!gCharsetMap
|| !gCharsetMap
->Init(NUM_CHARSETS
))
3893 return NS_ERROR_OUT_OF_MEMORY
;
3895 for (PRUint16 i
= 0; i
< NUM_CHARSETS
; i
++) {
3896 gCharsetMap
->Put(charsets
[i
].mozName
, charsets
[i
].javaName
);
3899 // if found mapping, return it; otherwise return original charset
3900 const char *mapping
;
3901 *result
= gCharsetMap
->Get(charset
.get(), &mapping
) ? PL_strdup(mapping
) :
3902 ToNewCString(charset
);
3905 return (*result
) ? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
3908 NS_IMETHODIMP
nsPluginInstanceOwner::GetAlignment(const char* *result
)
3910 return GetAttribute("ALIGN", result
);
3913 NS_IMETHODIMP
nsPluginInstanceOwner::GetWidth(PRUint32
*result
)
3915 NS_ENSURE_ARG_POINTER(result
);
3917 NS_ENSURE_TRUE(mPluginWindow
, NS_ERROR_NULL_POINTER
);
3919 *result
= mPluginWindow
->width
;
3924 NS_IMETHODIMP
nsPluginInstanceOwner::GetHeight(PRUint32
*result
)
3926 NS_ENSURE_ARG_POINTER(result
);
3928 NS_ENSURE_TRUE(mPluginWindow
, NS_ERROR_NULL_POINTER
);
3930 *result
= mPluginWindow
->height
;
3936 NS_IMETHODIMP
nsPluginInstanceOwner::GetBorderVertSpace(PRUint32
*result
)
3941 rv
= GetAttribute("VSPACE", &vspace
);
3945 *result
= (PRUint32
)atol(vspace
);
3955 NS_IMETHODIMP
nsPluginInstanceOwner::GetBorderHorizSpace(PRUint32
*result
)
3960 rv
= GetAttribute("HSPACE", &hspace
);
3964 *result
= (PRUint32
)atol(hspace
);
3974 NS_IMETHODIMP
nsPluginInstanceOwner::GetUniqueID(PRUint32
*result
)
3976 NS_ENSURE_ARG_POINTER(result
);
3977 *result
= NS_PTR_TO_INT32(mObjectFrame
);
3981 // Cache the attributes and/or parameters of our tag into a single set
3982 // of arrays to be compatible with Netscape 4.x. The attributes go first,
3983 // followed by a PARAM/null and then any PARAM tags. Also, hold the
3984 // cached array around for the duration of the life of the instance
3985 // because Netscape 4.x did. See bug 111008.
3986 nsresult
nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
3988 if (mCachedAttrParamValues
)
3991 NS_PRECONDITION(((mNumCachedAttrs
+ mNumCachedParams
) == 0) &&
3992 !mCachedAttrParamNames
,
3993 "re-cache of attrs/params not implemented! use the DOM "
3994 "node directy instead");
3995 NS_ENSURE_TRUE(mObjectFrame
, NS_ERROR_NULL_POINTER
);
3997 // Convert to a 16-bit count. Subtract 2 in case we add an extra
3998 // "src" or "wmode" entry below.
3999 PRUint32 cattrs
= mContent
->GetAttrCount();
4000 if (cattrs
< 0x0000FFFD) {
4001 mNumCachedAttrs
= static_cast<PRUint16
>(cattrs
);
4003 mNumCachedAttrs
= 0xFFFD;
4006 // now, we need to find all the PARAM tags that are children of us
4007 // however, be careful not to include any PARAMs that don't have us
4008 // as a direct parent. For nested object (or applet) tags, be sure
4009 // to only round up the param tags that coorespond with THIS
4010 // instance. And also, weed out any bogus tags that may get in the
4011 // way, see bug 39609. Then, with any param tag that meet our
4012 // qualification, temporarly cache them in an nsCOMArray until
4013 // we can figure out what size to make our fixed char* array.
4014 nsCOMArray
<nsIDOMElement
> ourParams
;
4016 // Get all dependent PARAM tags, even if they are not direct children.
4017 nsCOMPtr
<nsIDOMElement
> mydomElement
= do_QueryInterface(mContent
);
4018 NS_ENSURE_TRUE(mydomElement
, NS_ERROR_NO_INTERFACE
);
4020 // Making DOM method calls can cause our frame to go away.
4021 nsCOMPtr
<nsIPluginInstanceOwner
> kungFuDeathGrip(this);
4023 nsCOMPtr
<nsIDOMNodeList
> allParams
;
4024 NS_NAMED_LITERAL_STRING(xhtml_ns
, "http://www.w3.org/1999/xhtml");
4025 mydomElement
->GetElementsByTagNameNS(xhtml_ns
, NS_LITERAL_STRING("param"),
4026 getter_AddRefs(allParams
));
4028 PRUint32 numAllParams
;
4029 allParams
->GetLength(&numAllParams
);
4030 for (PRUint32 i
= 0; i
< numAllParams
; i
++) {
4031 nsCOMPtr
<nsIDOMNode
> pnode
;
4032 allParams
->Item(i
, getter_AddRefs(pnode
));
4033 nsCOMPtr
<nsIDOMElement
> domelement
= do_QueryInterface(pnode
);
4035 // Ignore params without a name attribute.
4037 domelement
->GetAttribute(NS_LITERAL_STRING("name"), name
);
4038 if (!name
.IsEmpty()) {
4039 // Find the first object or applet parent.
4040 nsCOMPtr
<nsIDOMNode
> parent
;
4041 nsCOMPtr
<nsIDOMHTMLObjectElement
> domobject
;
4042 nsCOMPtr
<nsIDOMHTMLAppletElement
> domapplet
;
4043 pnode
->GetParentNode(getter_AddRefs(parent
));
4044 while (!(domobject
|| domapplet
) && parent
) {
4045 domobject
= do_QueryInterface(parent
);
4046 domapplet
= do_QueryInterface(parent
);
4047 nsCOMPtr
<nsIDOMNode
> temp
;
4048 parent
->GetParentNode(getter_AddRefs(temp
));
4051 if (domapplet
|| domobject
) {
4058 nsCOMPtr
<nsIDOMNode
> mydomNode
= do_QueryInterface(mydomElement
);
4059 if (parent
== mydomNode
) {
4060 ourParams
.AppendObject(domelement
);
4068 // We're done with DOM method calls now. Make sure we still have a frame.
4069 NS_ENSURE_TRUE(mObjectFrame
, NS_ERROR_OUT_OF_MEMORY
);
4071 // Convert to a 16-bit count.
4072 PRUint32 cparams
= ourParams
.Count();
4073 if (cparams
< 0x0000FFFF) {
4074 mNumCachedParams
= static_cast<PRUint16
>(cparams
);
4076 mNumCachedParams
= 0xFFFF;
4079 PRUint16 numRealAttrs
= mNumCachedAttrs
;
4081 // Some plugins were never written to understand the "data" attribute of the OBJECT tag.
4082 // Real and WMP will not play unless they find a "src" attribute, see bug 152334.
4083 // Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
4084 // look for "data", lets instead copy the "data" attribute and add another entry
4085 // to the bottom of the array if there isn't already a "src" specified.
4087 if (mContent
->Tag() == nsGkAtoms::object
&&
4088 !mContent
->HasAttr(kNameSpaceID_None
, nsGkAtoms::src
) &&
4089 mContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::data
, data
) &&
4094 // "plugins.force.wmode" preference is forcing wmode type for plugins
4095 // possible values - "opaque", "transparent", "windowed"
4096 nsAdoptingCString wmodeType
= nsContentUtils::GetCharPref("plugins.force.wmode");
4097 if (!wmodeType
.IsEmpty()) {
4101 mCachedAttrParamNames
= (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs
+ 1 + mNumCachedParams
));
4102 NS_ENSURE_TRUE(mCachedAttrParamNames
, NS_ERROR_OUT_OF_MEMORY
);
4103 mCachedAttrParamValues
= (char**)NS_Alloc(sizeof(char*) * (mNumCachedAttrs
+ 1 + mNumCachedParams
));
4104 NS_ENSURE_TRUE(mCachedAttrParamValues
, NS_ERROR_OUT_OF_MEMORY
);
4106 // Some plugins (eg Flash, see bug 234675.) are actually sensitive to the
4107 // attribute order. So we want to make sure we give the plugin the
4108 // attributes in the order they came in in the source, to be compatible with
4109 // other browsers. Now in HTML, the storage order is the reverse of the
4110 // source order, while in XML and XHTML it's the same as the source order
4111 // (see the AddAttributes functions in the HTML and XML content sinks).
4112 PRInt32 start
, end
, increment
;
4113 if (mContent
->IsHTML() &&
4114 mContent
->IsInHTMLDocument()) {
4115 // HTML. Walk attributes in reverse order.
4116 start
= numRealAttrs
- 1;
4120 // XHTML or XML. Walk attributes in forward order.
4126 // Set to the next slot to fill in name and value cache arrays.
4127 PRUint32 nextAttrParamIndex
= 0;
4129 // Potentially add WMODE attribute.
4130 if (!wmodeType
.IsEmpty()) {
4131 mCachedAttrParamNames
[nextAttrParamIndex
] = ToNewUTF8String(NS_LITERAL_STRING("wmode"));
4132 mCachedAttrParamValues
[nextAttrParamIndex
] = ToNewUTF8String(NS_ConvertUTF8toUTF16(wmodeType
));
4133 nextAttrParamIndex
++;
4136 // Add attribute name/value pairs.
4137 for (PRInt32 index
= start
; index
!= end
; index
+= increment
) {
4138 const nsAttrName
* attrName
= mContent
->GetAttrNameAt(index
);
4139 nsIAtom
* atom
= attrName
->LocalName();
4141 mContent
->GetAttr(attrName
->NamespaceID(), atom
, value
);
4143 atom
->ToString(name
);
4145 FixUpURLS(name
, value
);
4147 mCachedAttrParamNames
[nextAttrParamIndex
] = ToNewUTF8String(name
);
4148 mCachedAttrParamValues
[nextAttrParamIndex
] = ToNewUTF8String(value
);
4149 nextAttrParamIndex
++;
4152 // Potentially add SRC attribute.
4153 if (!data
.IsEmpty()) {
4154 mCachedAttrParamNames
[nextAttrParamIndex
] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
4155 mCachedAttrParamValues
[nextAttrParamIndex
] = ToNewUTF8String(data
);
4156 nextAttrParamIndex
++;
4159 // Add PARAM and null separator.
4160 mCachedAttrParamNames
[nextAttrParamIndex
] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
4161 mCachedAttrParamValues
[nextAttrParamIndex
] = nsnull
;
4162 nextAttrParamIndex
++;
4164 // Add PARAM name/value pairs.
4165 for (PRUint16 i
= 0; i
< mNumCachedParams
; i
++) {
4166 nsIDOMElement
* param
= ourParams
.ObjectAt(i
);
4173 param
->GetAttribute(NS_LITERAL_STRING("name"), name
); // check for empty done above
4174 param
->GetAttribute(NS_LITERAL_STRING("value"), value
);
4176 FixUpURLS(name
, value
);
4179 * According to the HTML 4.01 spec, at
4180 * http://www.w3.org/TR/html4/types.html#type-cdata
4181 * ''User agents may ignore leading and trailing
4182 * white space in CDATA attribute values (e.g., "
4183 * myval " may be interpreted as "myval"). Authors
4184 * should not declare attribute values with
4185 * leading or trailing white space.''
4186 * However, do not trim consecutive spaces as in bug 122119
4188 name
.Trim(" \n\r\t\b", PR_TRUE
, PR_TRUE
, PR_FALSE
);
4189 value
.Trim(" \n\r\t\b", PR_TRUE
, PR_TRUE
, PR_FALSE
);
4190 mCachedAttrParamNames
[nextAttrParamIndex
] = ToNewUTF8String(name
);
4191 mCachedAttrParamValues
[nextAttrParamIndex
] = ToNewUTF8String(value
);
4192 nextAttrParamIndex
++;
4199 // Here's where we forward events to plugins.
4203 #ifndef NP_NO_CARBON
4204 static void InitializeEventRecord(EventRecord
* event
, Point
* aMousePosition
)
4206 memset(event
, 0, sizeof(EventRecord
));
4207 if (aMousePosition
) {
4208 event
->where
= *aMousePosition
;
4210 ::GetGlobalMouse(&event
->where
);
4212 event
->when
= ::TickCount();
4213 event
->modifiers
= ::GetCurrentKeyModifiers();
4217 static void InitializeNPCocoaEvent(NPCocoaEvent
* event
)
4219 memset(event
, 0, sizeof(NPCocoaEvent
));
4222 NPDrawingModel
nsPluginInstanceOwner::GetDrawingModel()
4224 #ifndef NP_NO_QUICKDRAW
4225 NPDrawingModel drawingModel
= NPDrawingModelQuickDraw
;
4227 NPDrawingModel drawingModel
= NPDrawingModelCoreGraphics
;
4231 return drawingModel
;
4233 mInstance
->GetDrawingModel((PRInt32
*)&drawingModel
);
4234 return drawingModel
;
4237 PRBool
nsPluginInstanceOwner::IsRemoteDrawingCoreAnimation()
4239 nsCOMPtr
<nsIPluginInstance_MOZILLA_2_0_BRANCH
> inst
= do_QueryInterface(mInstance
);
4243 PRBool coreAnimation
;
4244 if (!NS_SUCCEEDED(inst
->IsRemoteDrawingCoreAnimation(&coreAnimation
)))
4247 return coreAnimation
;
4250 NPEventModel
nsPluginInstanceOwner::GetEventModel()
4255 #define DEFAULT_REFRESH_RATE 20 // 50 FPS
4257 nsCOMPtr
<nsITimer
> *nsPluginInstanceOwner::sCATimer
= NULL
;
4258 nsTArray
<nsPluginInstanceOwner
*> *nsPluginInstanceOwner::sCARefreshListeners
= NULL
;
4260 void nsPluginInstanceOwner::CARefresh(nsITimer
*aTimer
, void *aClosure
) {
4261 if (!sCARefreshListeners
) {
4264 for (size_t i
= 0; i
< sCARefreshListeners
->Length(); i
++) {
4265 nsPluginInstanceOwner
* instanceOwner
= (*sCARefreshListeners
)[i
];
4267 instanceOwner
->GetWindow(window
);
4274 r
.right
= window
->width
;
4275 r
.bottom
= window
->height
;
4276 instanceOwner
->InvalidateRect(&r
);
4280 void nsPluginInstanceOwner::AddToCARefreshTimer(nsPluginInstanceOwner
*aPluginInstance
) {
4281 if (!sCARefreshListeners
) {
4282 sCARefreshListeners
= new nsTArray
<nsPluginInstanceOwner
*>();
4283 if (!sCARefreshListeners
) {
4288 NS_ASSERTION(!sCARefreshListeners
->Contains(aPluginInstance
),
4289 "pluginInstanceOwner already registered as a listener");
4290 sCARefreshListeners
->AppendElement(aPluginInstance
);
4293 sCATimer
= new nsCOMPtr
<nsITimer
>();
4299 if (sCARefreshListeners
->Length() == 1) {
4300 *sCATimer
= do_CreateInstance("@mozilla.org/timer;1");
4301 (*sCATimer
)->InitWithFuncCallback(CARefresh
, NULL
,
4302 DEFAULT_REFRESH_RATE
, nsITimer::TYPE_REPEATING_SLACK
);
4306 void nsPluginInstanceOwner::RemoveFromCARefreshTimer(nsPluginInstanceOwner
*aPluginInstance
) {
4307 if (!sCARefreshListeners
|| sCARefreshListeners
->Contains(aPluginInstance
) == false) {
4311 sCARefreshListeners
->RemoveElement(aPluginInstance
);
4313 if (sCARefreshListeners
->Length() == 0) {
4315 (*sCATimer
)->Cancel();
4319 delete sCARefreshListeners
;
4320 sCARefreshListeners
= NULL
;
4324 void nsPluginInstanceOwner::SetupCARefresh()
4326 const char* pluginType
= GetMIMEType(mInstance
);
4327 if (strcmp(pluginType
, "application/x-shockwave-flash") != 0) {
4328 // We don't need a timer since Flash is invoking InvalidateRect for us.
4329 AddToCARefreshTimer(this);
4333 void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext
,
4334 int aWidth
, int aHeight
)
4336 if (aWidth
== 0 || aHeight
== 0)
4340 (mIOSurface
->GetWidth() != (size_t)aWidth
||
4341 mIOSurface
->GetHeight() != (size_t)aHeight
)) {
4346 // If the renderer is backed by an IOSurface, resize it as required.
4347 mIOSurface
= nsIOSurface::CreateIOSurface(aWidth
, aHeight
);
4349 nsIOSurface
*attachSurface
= nsIOSurface::LookupSurface(
4350 mIOSurface
->GetIOSurfaceID());
4351 if (attachSurface
) {
4352 mCARenderer
.AttachIOSurface(attachSurface
);
4354 NS_ERROR("IOSurface attachment failed");
4355 delete attachSurface
;
4362 if (mCARenderer
.isInit() == false) {
4363 void *caLayer
= NULL
;
4364 mInstance
->GetValueFromPlugin(NPPVpluginCoreAnimationLayer
, &caLayer
);
4369 mCARenderer
.SetupRenderer(caLayer
, aWidth
, aHeight
);
4371 // Setting up the CALayer requires resetting the painting otherwise we
4372 // get garbage for the first few frames.
4373 FixUpPluginWindow(ePluginPaintDisable
);
4374 FixUpPluginWindow(ePluginPaintEnable
);
4377 CGImageRef caImage
= NULL
;
4378 nsresult rt
= mCARenderer
.Render(aWidth
, aHeight
, &caImage
);
4379 if (rt
== NS_OK
&& mIOSurface
) {
4380 nsCARenderer::DrawSurfaceToCGContext(aCGContext
, mIOSurface
, CreateSystemColorSpace(),
4381 0, 0, aWidth
, aHeight
);
4382 } else if (rt
== NS_OK
&& caImage
!= NULL
) {
4383 // Significant speed up by resetting the scaling
4384 ::CGContextSetInterpolationQuality(aCGContext
, kCGInterpolationNone
);
4385 ::CGContextTranslateCTM(aCGContext
, 0, aHeight
);
4386 ::CGContextScaleCTM(aCGContext
, 1.0, -1.0);
4388 ::CGContextDrawImage(aCGContext
, CGRectMake(0,0,aWidth
,aHeight
), caImage
);
4390 NS_NOTREACHED("nsCARenderer::Render failure");
4394 void* nsPluginInstanceOwner::GetPluginPortCopy()
4396 #ifndef NP_NO_QUICKDRAW
4397 if (GetDrawingModel() == NPDrawingModelQuickDraw
)
4398 return &mQDPluginPortCopy
;
4400 if (GetDrawingModel() == NPDrawingModelCoreGraphics
||
4401 GetDrawingModel() == NPDrawingModelCoreAnimation
||
4402 GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation
)
4403 return &mCGPluginPortCopy
;
4407 // Currently (on OS X in Cocoa widgets) any changes made as a result of
4408 // calling GetPluginPortFromWidget() are immediately reflected in the NPWindow
4409 // structure that has been passed to the plugin via SetWindow(). This is
4410 // because calls to nsChildView::GetNativeData(NS_NATIVE_PLUGIN_PORT_CG)
4411 // always return a pointer to the same internal (private) object, but may
4412 // make changes inside that object. All calls to GetPluginPortFromWidget() made while
4413 // the plugin is active (i.e. excluding those made at our initialization)
4414 // need to take this into account. The easiest way to do so is to replace
4415 // them with calls to SetPluginPortAndDetectChange(). This method keeps track
4416 // of when calls to GetPluginPortFromWidget() result in changes, and sets a flag to make
4417 // sure SetWindow() gets called the next time through FixUpPluginWindow(), so
4418 // that the plugin is notified of these changes.
4419 void* nsPluginInstanceOwner::SetPluginPortAndDetectChange()
4423 void* pluginPort
= GetPluginPortFromWidget();
4426 mPluginWindow
->window
= pluginPort
;
4428 #ifndef NP_NO_QUICKDRAW
4429 NPDrawingModel drawingModel
= GetDrawingModel();
4430 if (drawingModel
== NPDrawingModelQuickDraw
) {
4431 NP_Port
* windowQDPort
= static_cast<NP_Port
*>(mPluginWindow
->window
);
4432 if (windowQDPort
->port
!= mQDPluginPortCopy
.port
) {
4433 mQDPluginPortCopy
.port
= windowQDPort
->port
;
4434 mPluginPortChanged
= PR_TRUE
;
4436 } else if (drawingModel
== NPDrawingModelCoreGraphics
||
4437 drawingModel
== NPDrawingModelCoreAnimation
||
4438 drawingModel
== NPDrawingModelInvalidatingCoreAnimation
)
4441 #ifndef NP_NO_CARBON
4442 if (GetEventModel() == NPEventModelCarbon
) {
4443 NP_CGContext
* windowCGPort
= static_cast<NP_CGContext
*>(mPluginWindow
->window
);
4444 if ((windowCGPort
->context
!= mCGPluginPortCopy
.context
) ||
4445 (windowCGPort
->window
!= mCGPluginPortCopy
.window
)) {
4446 mCGPluginPortCopy
.context
= windowCGPort
->context
;
4447 mCGPluginPortCopy
.window
= windowCGPort
->window
;
4448 mPluginPortChanged
= PR_TRUE
;
4454 return mPluginWindow
->window
;
4457 void nsPluginInstanceOwner::BeginCGPaint()
4462 void nsPluginInstanceOwner::EndCGPaint()
4465 NS_ASSERTION(mInCGPaintLevel
>= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!");
4472 nsPluginInstanceOwner::GetEventloopNestingLevel()
4474 nsCOMPtr
<nsIAppShell
> appShell
= do_GetService(kAppShellCID
);
4475 PRUint32 currentLevel
= 0;
4477 appShell
->GetEventloopNestingLevel(¤tLevel
);
4479 // Cocoa widget code doesn't process UI events through the normal
4480 // appshell event loop, so it needs an additional count here.
4485 // No idea how this happens... but Linux doesn't consistently
4486 // process UI events through the appshell event loop. If we get a 0
4487 // here on any platform we increment the level just in case so that
4488 // we make sure we always tear the plugin down eventually.
4489 if (!currentLevel
) {
4493 return currentLevel
;
4496 void nsPluginInstanceOwner::ScrollPositionWillChange(nscoord aX
, nscoord aY
)
4498 #ifdef MAC_CARBON_PLUGINS
4499 if (GetEventModel() != NPEventModelCarbon
)
4505 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
4506 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
4507 EventRecord scrollEvent
;
4508 InitializeEventRecord(&scrollEvent
, nsnull
);
4509 scrollEvent
.what
= NPEventType_ScrollingBeginsEvent
;
4511 void* window
= FixUpPluginWindow(ePluginPaintDisable
);
4513 mInstance
->HandleEvent(&scrollEvent
, nsnull
);
4515 pluginWidget
->EndDrawPlugin();
4521 void nsPluginInstanceOwner::ScrollPositionDidChange(nscoord aX
, nscoord aY
)
4523 #ifdef MAC_CARBON_PLUGINS
4524 if (GetEventModel() != NPEventModelCarbon
)
4528 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
4529 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
4530 EventRecord scrollEvent
;
4531 InitializeEventRecord(&scrollEvent
, nsnull
);
4532 scrollEvent
.what
= NPEventType_ScrollingEndsEvent
;
4534 void* window
= FixUpPluginWindow(ePluginPaintEnable
);
4536 mInstance
->HandleEvent(&scrollEvent
, nsnull
);
4538 pluginWidget
->EndDrawPlugin();
4544 /*=============== nsIDOMFocusListener ======================*/
4545 nsresult
nsPluginInstanceOwner::Focus(nsIDOMEvent
* aFocusEvent
)
4547 mContentFocused
= PR_TRUE
;
4548 return DispatchFocusToPlugin(aFocusEvent
);
4551 nsresult
nsPluginInstanceOwner::Blur(nsIDOMEvent
* aFocusEvent
)
4553 mContentFocused
= PR_FALSE
;
4554 return DispatchFocusToPlugin(aFocusEvent
);
4557 nsresult
nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent
* aFocusEvent
)
4560 if (!mPluginWindow
|| (mPluginWindow
->type
== NPWindowTypeWindow
)) {
4561 // continue only for cases without child window
4562 return aFocusEvent
->PreventDefault(); // consume event
4566 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aFocusEvent
));
4568 nsEvent
* theEvent
= privateEvent
->GetInternalNSEvent();
4570 // we only care about the message in ProcessEvent
4571 nsGUIEvent
focusEvent(NS_IS_TRUSTED_EVENT(theEvent
), theEvent
->message
,
4573 nsEventStatus rv
= ProcessEvent(focusEvent
);
4574 if (nsEventStatus_eConsumeNoDefault
== rv
) {
4575 aFocusEvent
->PreventDefault();
4576 aFocusEvent
->StopPropagation();
4579 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, focusEvent null");
4581 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, privateEvent null");
4587 /*=============== nsIKeyListener ======================*/
4588 nsresult
nsPluginInstanceOwner::KeyDown(nsIDOMEvent
* aKeyEvent
)
4590 return DispatchKeyToPlugin(aKeyEvent
);
4593 nsresult
nsPluginInstanceOwner::KeyUp(nsIDOMEvent
* aKeyEvent
)
4595 return DispatchKeyToPlugin(aKeyEvent
);
4598 nsresult
nsPluginInstanceOwner::KeyPress(nsIDOMEvent
* aKeyEvent
)
4601 #ifndef NP_NO_CARBON
4602 if (GetEventModel() == NPEventModelCarbon
) {
4603 // KeyPress events are really synthesized keyDown events.
4604 // Here we check the native message of the event so that
4605 // we won't send the plugin two keyDown events.
4606 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aKeyEvent
));
4608 nsEvent
*theEvent
= privateEvent
->GetInternalNSEvent();
4609 const nsGUIEvent
*guiEvent
= (nsGUIEvent
*)theEvent
;
4610 const EventRecord
*ev
= (EventRecord
*)(guiEvent
->pluginEvent
);
4612 guiEvent
->message
== NS_KEY_PRESS
&&
4614 ev
->what
== keyDown
)
4615 return aKeyEvent
->PreventDefault(); // consume event
4618 // Nasty hack to avoid recursive event dispatching with Java. Java can
4619 // dispatch key events to a TSM handler, which comes back and calls
4620 // [ChildView insertText:] on the cocoa widget, which sends a key
4622 static PRBool sInKeyDispatch
= PR_FALSE
;
4625 return aKeyEvent
->PreventDefault(); // consume event
4627 sInKeyDispatch
= PR_TRUE
;
4628 nsresult rv
= DispatchKeyToPlugin(aKeyEvent
);
4629 sInKeyDispatch
= PR_FALSE
;
4634 return DispatchKeyToPlugin(aKeyEvent
);
4636 if (SendNativeEvents())
4637 DispatchKeyToPlugin(aKeyEvent
);
4640 // If this event is going to the plugin, we want to kill it.
4641 // Not actually sending keypress to the plugin, since we didn't before.
4642 aKeyEvent
->PreventDefault();
4643 aKeyEvent
->StopPropagation();
4649 nsresult
nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent
* aKeyEvent
)
4651 #if !defined(XP_MACOSX) && !defined(MOZ_COMPOSITED_PLUGINS)
4652 if (!mPluginWindow
|| (mPluginWindow
->type
== NPWindowTypeWindow
))
4653 return aKeyEvent
->PreventDefault(); // consume event
4654 // continue only for cases without child window
4658 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aKeyEvent
));
4660 nsKeyEvent
*keyEvent
= (nsKeyEvent
*) privateEvent
->GetInternalNSEvent();
4662 nsEventStatus rv
= ProcessEvent(*keyEvent
);
4663 if (nsEventStatus_eConsumeNoDefault
== rv
) {
4664 aKeyEvent
->PreventDefault();
4665 aKeyEvent
->StopPropagation();
4668 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, keyEvent null");
4670 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, privateEvent null");
4676 /*=============== nsIDOMMouseMotionListener ======================*/
4679 nsPluginInstanceOwner::MouseMove(nsIDOMEvent
* aMouseEvent
)
4681 #if !defined(XP_MACOSX)
4682 if (!mPluginWindow
|| (mPluginWindow
->type
== NPWindowTypeWindow
))
4683 return aMouseEvent
->PreventDefault(); // consume event
4684 // continue only for cases without child window
4687 // don't send mouse events if we are hidden
4688 if (!mWidgetVisible
)
4691 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aMouseEvent
));
4693 nsMouseEvent
* mouseEvent
= (nsMouseEvent
*) privateEvent
->GetInternalNSEvent();
4695 nsEventStatus rv
= ProcessEvent(*mouseEvent
);
4696 if (nsEventStatus_eConsumeNoDefault
== rv
) {
4697 return aMouseEvent
->PreventDefault(); // consume event
4700 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseMove failed, mouseEvent null");
4702 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseMove failed, privateEvent null");
4707 /*=============== nsIDOMMouseListener ======================*/
4710 nsPluginInstanceOwner::MouseDown(nsIDOMEvent
* aMouseEvent
)
4712 #if !defined(XP_MACOSX) && !defined(MOZ_COMPOSITED_PLUGINS)
4713 if (!mPluginWindow
|| (mPluginWindow
->type
== NPWindowTypeWindow
))
4714 return aMouseEvent
->PreventDefault(); // consume event
4715 // continue only for cases without child window
4718 // if the plugin is windowless, we need to set focus ourselves
4719 // otherwise, we might not get key events
4720 if (mObjectFrame
&& mPluginWindow
&&
4721 mPluginWindow
->type
== NPWindowTypeDrawable
) {
4723 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4725 nsCOMPtr
<nsIDOMElement
> elem
= do_QueryInterface(mContent
);
4726 fm
->SetFocus(elem
, 0);
4730 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aMouseEvent
));
4732 nsMouseEvent
* mouseEvent
= (nsMouseEvent
*) privateEvent
->GetInternalNSEvent();
4734 nsEventStatus rv
= ProcessEvent(*mouseEvent
);
4735 if (nsEventStatus_eConsumeNoDefault
== rv
) {
4736 return aMouseEvent
->PreventDefault(); // consume event
4739 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseDown failed, mouseEvent null");
4741 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::MouseDown failed, privateEvent null");
4747 nsPluginInstanceOwner::MouseUp(nsIDOMEvent
* aMouseEvent
)
4749 return DispatchMouseToPlugin(aMouseEvent
);
4753 nsPluginInstanceOwner::MouseClick(nsIDOMEvent
* aMouseEvent
)
4755 return DispatchMouseToPlugin(aMouseEvent
);
4759 nsPluginInstanceOwner::MouseDblClick(nsIDOMEvent
* aMouseEvent
)
4761 return DispatchMouseToPlugin(aMouseEvent
);
4765 nsPluginInstanceOwner::MouseOver(nsIDOMEvent
* aMouseEvent
)
4767 return DispatchMouseToPlugin(aMouseEvent
);
4771 nsPluginInstanceOwner::MouseOut(nsIDOMEvent
* aMouseEvent
)
4773 return DispatchMouseToPlugin(aMouseEvent
);
4776 nsresult
nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent
* aMouseEvent
)
4778 #if !defined(XP_MACOSX) && !defined(MOZ_COMPOSITED_PLUGINS)
4779 if (!mPluginWindow
|| (mPluginWindow
->type
== NPWindowTypeWindow
))
4780 return aMouseEvent
->PreventDefault(); // consume event
4781 // continue only for cases without child window
4783 // don't send mouse events if we are hidden
4784 if (!mWidgetVisible
)
4787 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aMouseEvent
));
4789 nsMouseEvent
* mouseEvent
= (nsMouseEvent
*) privateEvent
->GetInternalNSEvent();
4791 nsEventStatus rv
= ProcessEvent(*mouseEvent
);
4792 if (nsEventStatus_eConsumeNoDefault
== rv
) {
4793 aMouseEvent
->PreventDefault();
4794 aMouseEvent
->StopPropagation();
4797 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, mouseEvent null");
4799 else NS_ASSERTION(PR_FALSE
, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, privateEvent null");
4805 nsPluginInstanceOwner::HandleEvent(nsIDOMEvent
* aEvent
)
4808 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(aEvent
));
4809 nsCOMPtr
<nsIDOMDragEvent
> dragEvent(do_QueryInterface(aEvent
));
4810 if (privateEvent
&& dragEvent
) {
4811 nsEvent
* ievent
= privateEvent
->GetInternalNSEvent();
4812 if (ievent
&& NS_IS_TRUSTED_EVENT(ievent
) &&
4813 (ievent
->message
== NS_DRAGDROP_ENTER
|| ievent
->message
== NS_DRAGDROP_OVER
)) {
4814 // set the allowed effect to none here. The plugin should set it if necessary
4815 nsCOMPtr
<nsIDOMDataTransfer
> dataTransfer
;
4816 dragEvent
->GetDataTransfer(getter_AddRefs(dataTransfer
));
4818 dataTransfer
->SetEffectAllowed(NS_LITERAL_STRING("none"));
4821 // Let the plugin handle drag events.
4822 aEvent
->PreventDefault();
4823 aEvent
->StopPropagation();
4830 static unsigned int XInputEventState(const nsInputEvent
& anEvent
)
4832 unsigned int state
= 0;
4833 if (anEvent
.isShift
) state
|= ShiftMask
;
4834 if (anEvent
.isControl
) state
|= ControlMask
;
4835 if (anEvent
.isAlt
) state
|= Mod1Mask
;
4836 if (anEvent
.isMeta
) state
|= Mod4Mask
;
4841 #ifdef MOZ_COMPOSITED_PLUGINS
4842 static void find_dest_id(XID top
, XID
*root
, XID
*dest
, int target_x
, int target_y
)
4844 XID target_id
= top
;
4847 unsigned int nchildren
;
4849 Display
*display
= DefaultXDisplay();
4853 //printf("searching %x\n", target_id);
4854 if (!XQueryTree(display
, target_id
, root
, &parent
, &children
, &nchildren
) ||
4857 for (unsigned int i
=0; i
<nchildren
; i
++) {
4860 unsigned int width
, height
;
4861 unsigned int border_width
, depth
;
4862 XGetGeometry(display
, children
[i
], &root
, &x
, &y
,
4863 &width
, &height
, &border_width
,
4865 //printf("target: %d %d\n", target_x, target_y);
4866 //printf("geom: %dx%x @ %dx%d\n", width, height, x, y);
4867 // XXX: we may need to be more careful here, i.e. if
4868 // this condition matches more than one child
4869 if (target_x
>= x
&& target_y
>= y
&&
4870 target_x
<= x
+ int(width
) &&
4871 target_y
<= y
+ int(height
)) {
4872 target_id
= children
[i
];
4873 // printf("found new target: %x\n", target_id);
4879 /* no children contain the target */
4886 #ifdef MOZ_COMPOSITED_PLUGINS
4887 nsEventStatus
nsPluginInstanceOwner::ProcessEventX11Composited(const nsGUIEvent
& anEvent
)
4889 //printf("nsGUIEvent.message: %d\n", anEvent.message);
4890 nsEventStatus rv
= nsEventStatus_eIgnore
;
4891 if (!mInstance
|| !mObjectFrame
) // if mInstance is null, we shouldn't be here
4894 // this code supports windowless plugins
4895 nsIWidget
* widget
= anEvent
.widget
;
4897 pluginEvent
.type
= 0;
4899 switch(anEvent
.eventStructType
)
4901 case NS_MOUSE_EVENT
:
4903 switch (anEvent
.message
)
4905 case NS_MOUSE_CLICK
:
4906 case NS_MOUSE_DOUBLECLICK
:
4907 // Button up/down events sent instead.
4911 // Get reference point relative to plugin origin.
4912 const nsPresContext
* presContext
= mObjectFrame
->PresContext();
4914 nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent
, mObjectFrame
) -
4915 mObjectFrame
->GetUsedBorderAndPadding().TopLeft();
4916 nsIntPoint
pluginPoint(presContext
->AppUnitsToDevPixels(appPoint
.x
),
4917 presContext
->AppUnitsToDevPixels(appPoint
.y
));
4918 mLastPoint
= pluginPoint
;
4919 const nsMouseEvent
& mouseEvent
=
4920 static_cast<const nsMouseEvent
&>(anEvent
);
4921 // Get reference point relative to screen:
4922 nsIntPoint
rootPoint(-1,-1);
4924 rootPoint
= anEvent
.refPoint
+ widget
->WidgetToScreenOffset();
4925 #ifdef MOZ_WIDGET_GTK2
4926 Window root
= GDK_ROOT_WINDOW();
4927 #elif defined(MOZ_WIDGET_QT)
4928 Window root
= QX11Info::appRootWindow();
4933 switch (anEvent
.message
)
4935 case NS_MOUSE_ENTER_SYNTH
:
4936 case NS_MOUSE_EXIT_SYNTH
:
4938 XCrossingEvent
& event
= pluginEvent
.xcrossing
;
4939 event
.type
= anEvent
.message
== NS_MOUSE_ENTER_SYNTH
?
4940 EnterNotify
: LeaveNotify
;
4942 event
.time
= anEvent
.time
;
4943 event
.x
= pluginPoint
.x
;
4944 event
.y
= pluginPoint
.y
;
4945 event
.x_root
= rootPoint
.x
;
4946 event
.y_root
= rootPoint
.y
;
4947 event
.state
= XInputEventState(mouseEvent
);
4949 event
.subwindow
= None
;
4951 event
.detail
= NotifyDetailNone
;
4952 event
.same_screen
= True
;
4953 event
.focus
= mContentFocused
;
4958 XMotionEvent
& event
= pluginEvent
.xmotion
;
4959 event
.type
= MotionNotify
;
4961 event
.time
= anEvent
.time
;
4962 event
.x
= pluginPoint
.x
;
4963 event
.y
= pluginPoint
.y
;
4964 event
.x_root
= rootPoint
.x
;
4965 event
.y_root
= rootPoint
.y
;
4966 event
.state
= XInputEventState(mouseEvent
);
4968 event
.subwindow
= None
;
4969 event
.is_hint
= NotifyNormal
;
4970 event
.same_screen
= True
;
4972 be
.xmotion
= pluginEvent
.xmotion
;
4973 //printf("xmotion: %d %d\n", be.xmotion.x, be.xmotion.y);
4974 XID w
= (XID
)mPluginWindow
->window
;
4975 be
.xmotion
.window
= w
;
4976 XSendEvent (be
.xmotion
.display
, w
,
4977 FALSE
, ButtonMotionMask
, &be
);
4981 case NS_MOUSE_BUTTON_DOWN
:
4982 case NS_MOUSE_BUTTON_UP
:
4984 XButtonEvent
& event
= pluginEvent
.xbutton
;
4985 event
.type
= anEvent
.message
== NS_MOUSE_BUTTON_DOWN
?
4986 ButtonPress
: ButtonRelease
;
4988 event
.time
= anEvent
.time
;
4989 event
.x
= pluginPoint
.x
;
4990 event
.y
= pluginPoint
.y
;
4991 event
.x_root
= rootPoint
.x
;
4992 event
.y_root
= rootPoint
.y
;
4993 event
.state
= XInputEventState(mouseEvent
);
4994 switch (mouseEvent
.button
)
4996 case nsMouseEvent::eMiddleButton
:
4999 case nsMouseEvent::eRightButton
:
5002 default: // nsMouseEvent::eLeftButton;
5006 // information lost:
5007 event
.subwindow
= None
;
5008 event
.same_screen
= True
;
5014 unsigned int width
, height
, border_width
, depth
;
5016 //printf("xbutton: %d %d %d\n", anEvent.message, be.xbutton.x, be.xbutton.y);
5017 XID w
= (XID
)mPluginWindow
->window
;
5018 XGetGeometry(DefaultXDisplay(), w
, &root
, &wx
, &wy
, &width
, &height
, &border_width
, &depth
);
5019 find_dest_id(w
, &root
, &target
, pluginPoint
.x
+ wx
, pluginPoint
.y
+ wy
);
5020 be
.xbutton
.window
= target
;
5021 XSendEvent (DefaultXDisplay(), target
,
5022 FALSE
, event
.type
== ButtonPress
? ButtonPressMask
: ButtonReleaseMask
, &be
);
5030 //XXX case NS_MOUSE_SCROLL_EVENT: not received.
5033 if (anEvent
.pluginEvent
)
5035 XKeyEvent
&event
= pluginEvent
.xkey
;
5036 #ifdef MOZ_WIDGET_GTK2
5037 event
.root
= GDK_ROOT_WINDOW();
5038 event
.time
= anEvent
.time
;
5039 const GdkEventKey
* gdkEvent
=
5040 static_cast<const GdkEventKey
*>(anEvent
.pluginEvent
);
5041 event
.keycode
= gdkEvent
->hardware_keycode
;
5042 event
.state
= gdkEvent
->state
;
5043 switch (anEvent
.message
)
5046 // Handle NS_KEY_DOWN for modifier key presses
5047 // For non-modifiers we get NS_KEY_PRESS
5048 if (gdkEvent
->is_modifier
)
5049 event
.type
= XKeyPress
;
5052 event
.type
= XKeyPress
;
5055 event
.type
= KeyRelease
;
5060 #ifdef MOZ_WIDGET_QT
5061 const nsKeyEvent
& keyEvent
= static_cast<const nsKeyEvent
&>(anEvent
);
5063 memset( &event
, 0, sizeof(event
) );
5064 event
.time
= anEvent
.time
;
5066 QWidget
* qWidget
= static_cast<QWidget
*>(widget
->GetNativeData(NS_NATIVE_WINDOW
));
5068 event
.root
= qWidget
->x11Info().appRootWindow();
5070 // deduce keycode from the information in the attached QKeyEvent
5071 const QKeyEvent
* qtEvent
= static_cast<const QKeyEvent
*>(anEvent
.pluginEvent
);
5074 if (qtEvent
->nativeModifiers())
5075 event
.state
= qtEvent
->nativeModifiers();
5077 event
.state
= XInputEventState(keyEvent
);
5079 if (qtEvent
->nativeScanCode())
5080 event
.keycode
= qtEvent
->nativeScanCode();
5082 event
.keycode
= XKeysymToKeycode( (widget
? static_cast<Display
*>(widget
->GetNativeData(NS_NATIVE_DISPLAY
)) : nsnull
), qtEvent
->key());
5085 switch (anEvent
.message
)
5088 event
.type
= XKeyPress
;
5091 event
.type
= KeyRelease
;
5096 // Information that could be obtained from pluginEvent but we may not
5097 // want to promise to provide:
5098 event
.subwindow
= None
;
5103 event
.same_screen
= False
;
5109 unsigned int width
, height
, border_width
, depth
;
5111 //printf("xkey: %d %d %d\n", anEvent.message, be.xkey.keycode, be.xkey.state);
5112 XID w
= (XID
)mPluginWindow
->window
;
5113 XGetGeometry(DefaultXDisplay(), w
, &root
, &wx
, &wy
, &width
, &height
, &border_width
, &depth
);
5114 find_dest_id(w
, &root
, &target
, mLastPoint
.x
+ wx
, mLastPoint
.y
+ wy
);
5115 be
.xkey
.window
= target
;
5116 XSendEvent (DefaultXDisplay(), target
,
5117 FALSE
, event
.type
== XKeyPress
? KeyPressMask
: KeyReleaseMask
, &be
);
5123 // If we need to send synthesized key events, then
5124 // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
5125 // gdk_keymap_get_entries_for_keyval will be useful, but the
5126 // mappings will not be unique.
5127 NS_WARNING("Synthesized key event not sent to plugin");
5132 switch (anEvent
.message
)
5134 case NS_FOCUS_CONTENT
:
5135 case NS_BLUR_CONTENT
:
5137 XFocusChangeEvent
&event
= pluginEvent
.xfocus
;
5139 anEvent
.message
== NS_FOCUS_CONTENT
? FocusIn
: FocusOut
;
5140 // information lost:
5142 event
.detail
= NotifyDetailNone
;
5148 if (!pluginEvent
.type
) {
5149 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
5150 ("Unhandled event message %d with struct type %d\n",
5151 anEvent
.message
, anEvent
.eventStructType
));
5155 // Fill in (useless) generic event information.
5156 XAnyEvent
& event
= pluginEvent
.xany
;
5157 event
.display
= widget
?
5158 static_cast<Display
*>(widget
->GetNativeData(NS_NATIVE_DISPLAY
)) : nsnull
;
5159 event
.window
= None
; // not a real window
5160 // information lost:
5162 event
.send_event
= False
;
5165 /* we've sent the event via XSendEvent so don't send it directly to the plugin */
5166 PRInt16 response
= kNPEventNotHandled
;
5167 mInstance
->HandleEvent(&pluginEvent
, &response
);
5168 if (response
== kNPEventHandled
)
5169 rv
= nsEventStatus_eConsumeNoDefault
;
5176 nsEventStatus
nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent
& anEvent
)
5178 // printf("nsGUIEvent.message: %d\n", anEvent.message);
5180 #ifdef MOZ_COMPOSITED_PLUGINS
5181 if (mPluginWindow
&& (mPluginWindow
->type
!= NPWindowTypeDrawable
))
5182 return ProcessEventX11Composited(anEvent
);
5185 nsEventStatus rv
= nsEventStatus_eIgnore
;
5187 if (!mInstance
|| !mObjectFrame
) // if mInstance is null, we shouldn't be here
5188 return nsEventStatus_eIgnore
;
5192 return nsEventStatus_eIgnore
;
5194 // we never care about synthesized mouse enter
5195 if (anEvent
.message
== NS_MOUSE_ENTER_SYNTH
)
5196 return nsEventStatus_eIgnore
;
5198 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
5199 if (!pluginWidget
|| NS_FAILED(pluginWidget
->StartDrawPlugin()))
5200 return nsEventStatus_eIgnore
;
5202 NPEventModel eventModel
= GetEventModel();
5204 // If we have to synthesize an event we'll use one of these.
5205 #ifndef NP_NO_CARBON
5206 EventRecord synthCarbonEvent
;
5208 NPCocoaEvent synthCocoaEvent
;
5209 void* event
= anEvent
.pluginEvent
;
5211 nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent
, mObjectFrame
) -
5212 mObjectFrame
->GetUsedBorderAndPadding().TopLeft();
5213 nsPresContext
* presContext
= mObjectFrame
->PresContext();
5214 nsIntPoint
ptPx(presContext
->AppUnitsToDevPixels(pt
.x
),
5215 presContext
->AppUnitsToDevPixels(pt
.y
));
5216 #ifndef NP_NO_CARBON
5217 nsIntPoint geckoScreenCoords
= mWidget
->WidgetToScreenOffset();
5218 Point carbonPt
= { ptPx
.y
+ geckoScreenCoords
.y
, ptPx
.x
+ geckoScreenCoords
.x
};
5219 if (eventModel
== NPEventModelCarbon
) {
5220 if (event
&& anEvent
.eventStructType
== NS_MOUSE_EVENT
) {
5221 static_cast<EventRecord
*>(event
)->where
= carbonPt
;
5226 #ifndef NP_NO_CARBON
5227 if (eventModel
== NPEventModelCarbon
) {
5228 InitializeEventRecord(&synthCarbonEvent
, &carbonPt
);
5232 InitializeNPCocoaEvent(&synthCocoaEvent
);
5235 switch (anEvent
.message
) {
5236 case NS_FOCUS_CONTENT
:
5237 case NS_BLUR_CONTENT
:
5238 #ifndef NP_NO_CARBON
5239 if (eventModel
== NPEventModelCarbon
) {
5240 synthCarbonEvent
.what
= (anEvent
.message
== NS_FOCUS_CONTENT
) ?
5241 NPEventType_GetFocusEvent
: NPEventType_LoseFocusEvent
;
5242 event
= &synthCarbonEvent
;
5248 // Ignore mouse-moved events that happen as part of a dragging
5249 // operation that started over another frame. See bug 525078.
5250 nsCOMPtr
<nsFrameSelection
> frameselection
= mObjectFrame
->GetFrameSelection();
5251 if (!frameselection
->GetMouseDownState() ||
5252 (nsIPresShell::GetCapturingContent() == mObjectFrame
->GetContent())) {
5253 #ifndef NP_NO_CARBON
5254 if (eventModel
== NPEventModelCarbon
) {
5255 synthCarbonEvent
.what
= osEvt
;
5256 event
= &synthCarbonEvent
;
5260 synthCocoaEvent
.type
= NPCocoaEventMouseMoved
;
5261 synthCocoaEvent
.data
.mouse
.pluginX
= static_cast<double>(ptPx
.x
);
5262 synthCocoaEvent
.data
.mouse
.pluginY
= static_cast<double>(ptPx
.y
);
5263 event
= &synthCocoaEvent
;
5268 case NS_MOUSE_BUTTON_DOWN
:
5269 #ifndef NP_NO_CARBON
5270 if (eventModel
== NPEventModelCarbon
) {
5271 synthCarbonEvent
.what
= mouseDown
;
5272 event
= &synthCarbonEvent
;
5276 synthCocoaEvent
.type
= NPCocoaEventMouseDown
;
5277 synthCocoaEvent
.data
.mouse
.pluginX
= static_cast<double>(ptPx
.x
);
5278 synthCocoaEvent
.data
.mouse
.pluginY
= static_cast<double>(ptPx
.y
);
5279 event
= &synthCocoaEvent
;
5282 case NS_MOUSE_BUTTON_UP
:
5283 // If we're in a dragging operation that started over another frame,
5284 // either ignore the mouse-up event (in the Carbon Event Model) or
5285 // convert it into a mouse-entered event (in the Cocoa Event Model).
5287 if ((static_cast<const nsMouseEvent
&>(anEvent
).button
== nsMouseEvent::eLeftButton
) &&
5288 (nsIPresShell::GetCapturingContent() != mObjectFrame
->GetContent())) {
5289 if (eventModel
== NPEventModelCocoa
) {
5290 synthCocoaEvent
.type
= NPCocoaEventMouseEntered
;
5291 synthCocoaEvent
.data
.mouse
.pluginX
= static_cast<double>(ptPx
.x
);
5292 synthCocoaEvent
.data
.mouse
.pluginY
= static_cast<double>(ptPx
.y
);
5293 event
= &synthCocoaEvent
;
5296 #ifndef NP_NO_CARBON
5297 if (eventModel
== NPEventModelCarbon
) {
5298 synthCarbonEvent
.what
= mouseUp
;
5299 event
= &synthCarbonEvent
;
5303 synthCocoaEvent
.type
= NPCocoaEventMouseUp
;
5304 synthCocoaEvent
.data
.mouse
.pluginX
= static_cast<double>(ptPx
.x
);
5305 synthCocoaEvent
.data
.mouse
.pluginY
= static_cast<double>(ptPx
.y
);
5306 event
= &synthCocoaEvent
;
5314 // If we still don't have an event, bail.
5316 pluginWidget
->EndDrawPlugin();
5317 return nsEventStatus_eIgnore
;
5321 #ifndef NP_NO_CARBON
5322 // Work around an issue in the Flash plugin, which can cache a pointer
5323 // to a doomed TSM document (one that belongs to a NSTSMInputContext)
5324 // and try to activate it after it has been deleted. See bug 183313.
5325 if (eventModel
== NPEventModelCarbon
&& anEvent
.message
== NS_FOCUS_CONTENT
)
5326 ::DeactivateTSMDocument(::TSMGetActiveDocument());
5329 PRInt16 response
= kNPEventNotHandled
;
5330 void* window
= FixUpPluginWindow(ePluginPaintEnable
);
5331 if (window
|| (eventModel
== NPEventModelCocoa
)) {
5332 mInstance
->HandleEvent(event
, &response
);
5335 if (eventModel
== NPEventModelCocoa
&& response
== kNPEventStartIME
) {
5336 pluginWidget
->StartComplexTextInputForCurrentEvent();
5339 if ((response
== kNPEventHandled
|| response
== kNPEventStartIME
) &&
5340 !(anEvent
.eventStructType
== NS_MOUSE_EVENT
&&
5341 anEvent
.message
== NS_MOUSE_BUTTON_DOWN
&&
5342 static_cast<const nsMouseEvent
&>(anEvent
).button
== nsMouseEvent::eLeftButton
&&
5344 rv
= nsEventStatus_eConsumeNoDefault
;
5346 pluginWidget
->EndDrawPlugin();
5350 // this code supports windowless plugins
5351 NPEvent
*pPluginEvent
= (NPEvent
*)anEvent
.pluginEvent
;
5352 // we can get synthetic events from the nsEventStateManager... these
5353 // have no pluginEvent
5354 NPEvent pluginEvent
;
5355 if (anEvent
.eventStructType
== NS_MOUSE_EVENT
) {
5356 if (!pPluginEvent
) {
5357 // XXX Should extend this list to synthesize events for more event
5359 pluginEvent
.event
= 0;
5360 const nsMouseEvent
* mouseEvent
= static_cast<const nsMouseEvent
*>(&anEvent
);
5361 switch (anEvent
.message
) {
5363 pluginEvent
.event
= WM_MOUSEMOVE
;
5365 case NS_MOUSE_BUTTON_DOWN
: {
5366 static const int downMsgs
[] =
5367 { WM_LBUTTONDOWN
, WM_MBUTTONDOWN
, WM_RBUTTONDOWN
};
5368 static const int dblClickMsgs
[] =
5369 { WM_LBUTTONDBLCLK
, WM_MBUTTONDBLCLK
, WM_RBUTTONDBLCLK
};
5370 if (mouseEvent
->clickCount
== 2) {
5371 pluginEvent
.event
= dblClickMsgs
[mouseEvent
->button
];
5373 pluginEvent
.event
= downMsgs
[mouseEvent
->button
];
5377 case NS_MOUSE_BUTTON_UP
: {
5378 static const int upMsgs
[] =
5379 { WM_LBUTTONUP
, WM_MBUTTONUP
, WM_RBUTTONUP
};
5380 pluginEvent
.event
= upMsgs
[mouseEvent
->button
];
5383 // don't synthesize anything for NS_MOUSE_DOUBLECLICK, since that
5384 // is a synthetic event generated on mouse-up, and Windows WM_*DBLCLK
5385 // messages are sent on mouse-down
5389 if (pluginEvent
.event
) {
5390 pPluginEvent
= &pluginEvent
;
5391 pluginEvent
.wParam
=
5392 (::GetKeyState(VK_CONTROL
) ? MK_CONTROL
: 0) |
5393 (::GetKeyState(VK_SHIFT
) ? MK_SHIFT
: 0) |
5394 (::GetKeyState(VK_LBUTTON
) ? MK_LBUTTON
: 0) |
5395 (::GetKeyState(VK_MBUTTON
) ? MK_MBUTTON
: 0) |
5396 (::GetKeyState(VK_RBUTTON
) ? MK_RBUTTON
: 0) |
5397 (::GetKeyState(VK_XBUTTON1
) ? MK_XBUTTON1
: 0) |
5398 (::GetKeyState(VK_XBUTTON2
) ? MK_XBUTTON2
: 0);
5402 // Make event coordinates relative to our enclosing widget,
5403 // not the widget they were received on.
5404 // See use of NPEvent in widget/src/windows/nsWindow.cpp
5405 // for why this assert should be safe
5406 NS_ASSERTION(anEvent
.message
== NS_MOUSE_BUTTON_DOWN
||
5407 anEvent
.message
== NS_MOUSE_BUTTON_UP
||
5408 anEvent
.message
== NS_MOUSE_DOUBLECLICK
||
5409 anEvent
.message
== NS_MOUSE_ENTER_SYNTH
||
5410 anEvent
.message
== NS_MOUSE_EXIT_SYNTH
||
5411 anEvent
.message
== NS_MOUSE_MOVE
,
5412 "Incorrect event type for coordinate translation");
5414 nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent
, mObjectFrame
) -
5415 mObjectFrame
->GetUsedBorderAndPadding().TopLeft();
5416 nsPresContext
* presContext
= mObjectFrame
->PresContext();
5417 nsIntPoint
ptPx(presContext
->AppUnitsToDevPixels(pt
.x
),
5418 presContext
->AppUnitsToDevPixels(pt
.y
));
5419 nsIntPoint widgetPtPx
= ptPx
+ mObjectFrame
->GetWindowOriginInPixels(PR_TRUE
);
5420 pPluginEvent
->lParam
= MAKELPARAM(widgetPtPx
.x
, widgetPtPx
.y
);
5423 else if (!pPluginEvent
) {
5424 switch (anEvent
.message
) {
5425 case NS_FOCUS_CONTENT
:
5426 pluginEvent
.event
= WM_SETFOCUS
;
5427 pluginEvent
.wParam
= 0;
5428 pluginEvent
.lParam
= 0;
5429 pPluginEvent
= &pluginEvent
;
5431 case NS_BLUR_CONTENT
:
5432 pluginEvent
.event
= WM_KILLFOCUS
;
5433 pluginEvent
.wParam
= 0;
5434 pluginEvent
.lParam
= 0;
5435 pPluginEvent
= &pluginEvent
;
5440 if (pPluginEvent
&& !pPluginEvent
->event
) {
5441 // Don't send null events to plugins.
5442 NS_WARNING("nsObjectFrame ProcessEvent: trying to send null event to plugin.");
5447 PRInt16 response
= kNPEventNotHandled
;
5448 mInstance
->HandleEvent(pPluginEvent
, &response
);
5449 if (response
== kNPEventHandled
)
5450 rv
= nsEventStatus_eConsumeNoDefault
;
5455 // this code supports windowless plugins
5456 nsIWidget
* widget
= anEvent
.widget
;
5457 XEvent pluginEvent
= XEvent();
5458 pluginEvent
.type
= 0;
5460 switch(anEvent
.eventStructType
)
5462 case NS_MOUSE_EVENT
:
5464 switch (anEvent
.message
)
5466 case NS_MOUSE_CLICK
:
5467 case NS_MOUSE_DOUBLECLICK
:
5468 // Button up/down events sent instead.
5472 // Get reference point relative to plugin origin.
5473 const nsPresContext
* presContext
= mObjectFrame
->PresContext();
5475 nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent
, mObjectFrame
) -
5476 mObjectFrame
->GetUsedBorderAndPadding().TopLeft();
5477 nsIntPoint
pluginPoint(presContext
->AppUnitsToDevPixels(appPoint
.x
),
5478 presContext
->AppUnitsToDevPixels(appPoint
.y
));
5479 const nsMouseEvent
& mouseEvent
=
5480 static_cast<const nsMouseEvent
&>(anEvent
);
5481 // Get reference point relative to screen:
5482 nsIntPoint
rootPoint(-1,-1);
5484 rootPoint
= anEvent
.refPoint
+ widget
->WidgetToScreenOffset();
5485 #ifdef MOZ_WIDGET_GTK2
5486 Window root
= GDK_ROOT_WINDOW();
5487 #elif defined(MOZ_WIDGET_QT)
5488 Window root
= QX11Info::appRootWindow();
5490 Window root
= None
; // Could XQueryTree, but this is not important.
5493 switch (anEvent
.message
)
5495 case NS_MOUSE_ENTER_SYNTH
:
5496 case NS_MOUSE_EXIT_SYNTH
:
5498 XCrossingEvent
& event
= pluginEvent
.xcrossing
;
5499 event
.type
= anEvent
.message
== NS_MOUSE_ENTER_SYNTH
?
5500 EnterNotify
: LeaveNotify
;
5502 event
.time
= anEvent
.time
;
5503 event
.x
= pluginPoint
.x
;
5504 event
.y
= pluginPoint
.y
;
5505 event
.x_root
= rootPoint
.x
;
5506 event
.y_root
= rootPoint
.y
;
5507 event
.state
= XInputEventState(mouseEvent
);
5509 event
.subwindow
= None
;
5511 event
.detail
= NotifyDetailNone
;
5512 event
.same_screen
= True
;
5513 event
.focus
= mContentFocused
;
5518 XMotionEvent
& event
= pluginEvent
.xmotion
;
5519 event
.type
= MotionNotify
;
5521 event
.time
= anEvent
.time
;
5522 event
.x
= pluginPoint
.x
;
5523 event
.y
= pluginPoint
.y
;
5524 event
.x_root
= rootPoint
.x
;
5525 event
.y_root
= rootPoint
.y
;
5526 event
.state
= XInputEventState(mouseEvent
);
5528 event
.subwindow
= None
;
5529 event
.is_hint
= NotifyNormal
;
5530 event
.same_screen
= True
;
5533 case NS_MOUSE_BUTTON_DOWN
:
5534 case NS_MOUSE_BUTTON_UP
:
5536 XButtonEvent
& event
= pluginEvent
.xbutton
;
5537 event
.type
= anEvent
.message
== NS_MOUSE_BUTTON_DOWN
?
5538 ButtonPress
: ButtonRelease
;
5540 event
.time
= anEvent
.time
;
5541 event
.x
= pluginPoint
.x
;
5542 event
.y
= pluginPoint
.y
;
5543 event
.x_root
= rootPoint
.x
;
5544 event
.y_root
= rootPoint
.y
;
5545 event
.state
= XInputEventState(mouseEvent
);
5546 switch (mouseEvent
.button
)
5548 case nsMouseEvent::eMiddleButton
:
5551 case nsMouseEvent::eRightButton
:
5554 default: // nsMouseEvent::eLeftButton;
5558 // information lost:
5559 event
.subwindow
= None
;
5560 event
.same_screen
= True
;
5567 //XXX case NS_MOUSE_SCROLL_EVENT: not received.
5570 if (anEvent
.pluginEvent
)
5572 XKeyEvent
&event
= pluginEvent
.xkey
;
5573 #ifdef MOZ_WIDGET_GTK2
5574 event
.root
= GDK_ROOT_WINDOW();
5575 event
.time
= anEvent
.time
;
5576 const GdkEventKey
* gdkEvent
=
5577 static_cast<const GdkEventKey
*>(anEvent
.pluginEvent
);
5578 event
.keycode
= gdkEvent
->hardware_keycode
;
5579 event
.state
= gdkEvent
->state
;
5580 switch (anEvent
.message
)
5583 // Handle NS_KEY_DOWN for modifier key presses
5584 // For non-modifiers we get NS_KEY_PRESS
5585 if (gdkEvent
->is_modifier
)
5586 event
.type
= XKeyPress
;
5589 event
.type
= XKeyPress
;
5592 event
.type
= KeyRelease
;
5597 #ifdef MOZ_WIDGET_QT
5598 const nsKeyEvent
& keyEvent
= static_cast<const nsKeyEvent
&>(anEvent
);
5600 memset( &event
, 0, sizeof(event
) );
5601 event
.time
= anEvent
.time
;
5603 QWidget
* qWidget
= static_cast<QWidget
*>(widget
->GetNativeData(NS_NATIVE_WINDOW
));
5605 event
.root
= qWidget
->x11Info().appRootWindow();
5607 // deduce keycode from the information in the attached QKeyEvent
5608 const QKeyEvent
* qtEvent
= static_cast<const QKeyEvent
*>(anEvent
.pluginEvent
);
5611 if (qtEvent
->nativeModifiers())
5612 event
.state
= qtEvent
->nativeModifiers();
5614 event
.state
= XInputEventState(keyEvent
);
5616 if (qtEvent
->nativeScanCode())
5617 event
.keycode
= qtEvent
->nativeScanCode();
5619 event
.keycode
= XKeysymToKeycode( (widget
? static_cast<Display
*>(widget
->GetNativeData(NS_NATIVE_DISPLAY
)) : nsnull
), qtEvent
->key());
5622 switch (anEvent
.message
)
5625 event
.type
= XKeyPress
;
5628 event
.type
= KeyRelease
;
5632 // Information that could be obtained from pluginEvent but we may not
5633 // want to promise to provide:
5634 event
.subwindow
= None
;
5639 event
.same_screen
= False
;
5643 // If we need to send synthesized key events, then
5644 // DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
5645 // gdk_keymap_get_entries_for_keyval will be useful, but the
5646 // mappings will not be unique.
5647 NS_WARNING("Synthesized key event not sent to plugin");
5652 switch (anEvent
.message
)
5654 case NS_FOCUS_CONTENT
:
5655 case NS_BLUR_CONTENT
:
5657 XFocusChangeEvent
&event
= pluginEvent
.xfocus
;
5659 anEvent
.message
== NS_FOCUS_CONTENT
? FocusIn
: FocusOut
;
5660 // information lost:
5662 event
.detail
= NotifyDetailNone
;
5668 if (!pluginEvent
.type
) {
5669 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
5670 ("Unhandled event message %d with struct type %d\n",
5671 anEvent
.message
, anEvent
.eventStructType
));
5675 // Fill in (useless) generic event information.
5676 XAnyEvent
& event
= pluginEvent
.xany
;
5677 event
.display
= widget
?
5678 static_cast<Display
*>(widget
->GetNativeData(NS_NATIVE_DISPLAY
)) : nsnull
;
5679 event
.window
= None
; // not a real window
5680 // information lost:
5682 event
.send_event
= False
;
5684 PRInt16 response
= kNPEventNotHandled
;
5685 mInstance
->HandleEvent(&pluginEvent
, &response
);
5686 if (response
== kNPEventHandled
)
5687 rv
= nsEventStatus_eConsumeNoDefault
;
5694 nsPluginInstanceOwner::Destroy()
5696 #ifdef MAC_CARBON_PLUGINS
5697 // stop the timer explicitly to reduce reference count.
5701 RemoveFromCARefreshTimer(this);
5706 // unregister context menu listener
5707 if (mCXMenuListener
) {
5708 mCXMenuListener
->Destroy(mContent
);
5709 mCXMenuListener
= nsnull
;
5712 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(mContent
));
5715 nsCOMPtr
<nsIDOMEventListener
> listener
;
5716 QueryInterface(NS_GET_IID(nsIDOMEventListener
), getter_AddRefs(listener
));
5718 // Unregister focus event listener
5719 mContent
->RemoveEventListenerByIID(listener
, NS_GET_IID(nsIDOMFocusListener
));
5721 // Unregister mouse event listener
5722 mContent
->RemoveEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseListener
));
5724 // now for the mouse motion listener
5725 mContent
->RemoveEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseMotionListener
));
5727 // Unregister key event listener;
5728 target
->RemoveEventListener(NS_LITERAL_STRING("keypress"), listener
, PR_TRUE
);
5729 target
->RemoveEventListener(NS_LITERAL_STRING("keydown"), listener
, PR_TRUE
);
5730 target
->RemoveEventListener(NS_LITERAL_STRING("keyup"), listener
, PR_TRUE
);
5732 // Unregister drag event listener;
5733 target
->RemoveEventListener(NS_LITERAL_STRING("drop"), listener
, PR_TRUE
);
5734 target
->RemoveEventListener(NS_LITERAL_STRING("dragdrop"), listener
, PR_TRUE
);
5735 target
->RemoveEventListener(NS_LITERAL_STRING("drag"), listener
, PR_TRUE
);
5736 target
->RemoveEventListener(NS_LITERAL_STRING("dragenter"), listener
, PR_TRUE
);
5737 target
->RemoveEventListener(NS_LITERAL_STRING("dragover"), listener
, PR_TRUE
);
5738 target
->RemoveEventListener(NS_LITERAL_STRING("dragexit"), listener
, PR_TRUE
);
5739 target
->RemoveEventListener(NS_LITERAL_STRING("dragleave"), listener
, PR_TRUE
);
5740 target
->RemoveEventListener(NS_LITERAL_STRING("dragstart"), listener
, PR_TRUE
);
5741 target
->RemoveEventListener(NS_LITERAL_STRING("draggesture"), listener
, PR_TRUE
);
5742 target
->RemoveEventListener(NS_LITERAL_STRING("dragend"), listener
, PR_TRUE
);
5746 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
5748 pluginWidget
->SetPluginInstanceOwner(nsnull
);
5761 nsPluginInstanceOwner::PrepareToStop(PRBool aDelayedStop
)
5763 // Drop image reference because the child may destroy the surface after we return.
5764 nsRefPtr
<ImageContainer
> container
= mObjectFrame
->GetImageContainer();
5766 container
->SetCurrentImage(nsnull
);
5769 #if defined(XP_WIN) || defined(MOZ_X11)
5770 if (aDelayedStop
&& mWidget
) {
5771 // To delay stopping a plugin we need to reparent the plugin
5772 // so that we can safely tear down the
5773 // plugin after its frame (and view) is gone.
5775 // Also hide and disable the widget to avoid it from appearing in
5776 // odd places after reparenting it, but before it gets destroyed.
5777 mWidget
->Show(PR_FALSE
);
5778 mWidget
->Enable(PR_FALSE
);
5780 // Reparent the plugins native window. This relies on the widget
5781 // and plugin et al not holding any other references to its
5783 mWidget
->SetParent(nsnull
);
5785 mDestroyWidget
= PR_TRUE
;
5789 // Unregister scroll position listeners
5790 for (nsIFrame
* f
= mObjectFrame
; f
; f
= nsLayoutUtils::GetCrossDocParentFrame(f
)) {
5791 nsIScrollableFrame
* sf
= do_QueryFrame(f
);
5793 sf
->RemoveScrollPositionListener(this);
5798 // Paints are handled differently, so we just simulate an update event.
5801 void nsPluginInstanceOwner::Paint(const gfxRect
& aDirtyRect
, CGContextRef cgContext
)
5803 if (!mInstance
|| !mObjectFrame
)
5806 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
5807 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
5808 #ifndef NP_NO_CARBON
5809 void* window
= FixUpPluginWindow(ePluginPaintEnable
);
5810 if (GetEventModel() == NPEventModelCarbon
&& window
) {
5811 EventRecord updateEvent
;
5812 InitializeEventRecord(&updateEvent
, nsnull
);
5813 updateEvent
.what
= updateEvt
;
5814 updateEvent
.message
= UInt32(window
);
5816 mInstance
->HandleEvent(&updateEvent
, nsnull
);
5817 } else if (GetEventModel() == NPEventModelCocoa
)
5820 DoCocoaEventDrawRect(aDirtyRect
, cgContext
);
5822 pluginWidget
->EndDrawPlugin();
5826 void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect
& aDrawRect
, CGContextRef cgContext
)
5828 // The context given here is only valid during the HandleEvent call.
5829 NPCocoaEvent updateEvent
;
5830 InitializeNPCocoaEvent(&updateEvent
);
5831 updateEvent
.type
= NPCocoaEventDrawRect
;
5832 updateEvent
.data
.draw
.context
= cgContext
;
5833 updateEvent
.data
.draw
.x
= aDrawRect
.X();
5834 updateEvent
.data
.draw
.y
= aDrawRect
.Y();
5835 updateEvent
.data
.draw
.width
= aDrawRect
.Width();
5836 updateEvent
.data
.draw
.height
= aDrawRect
.Height();
5838 mInstance
->HandleEvent(&updateEvent
, nsnull
);
5843 void nsPluginInstanceOwner::Paint(const RECT
& aDirty
, HDC aDC
)
5845 if (!mInstance
|| !mObjectFrame
)
5848 NPEvent pluginEvent
;
5849 pluginEvent
.event
= WM_PAINT
;
5850 pluginEvent
.wParam
= WPARAM(aDC
);
5851 pluginEvent
.lParam
= LPARAM(&aDirty
);
5852 mInstance
->HandleEvent(&pluginEvent
, nsnull
);
5857 void nsPluginInstanceOwner::Paint(const nsRect
& aDirtyRect
, HPS aHPS
)
5859 if (!mInstance
|| !mObjectFrame
)
5864 nsIntRect relDirtyRect
= aDirtyRect
.ToOutsidePixels(mObjectFrame
->PresContext()->AppUnitsPerDevPixel());
5866 // we got dirty rectangle in relative window coordinates, but we
5867 // need it in absolute units and in the (left, top, right, bottom) form
5869 rectl
.xLeft
= relDirtyRect
.x
+ window
->x
;
5870 rectl
.yBottom
= relDirtyRect
.y
+ window
->y
;
5871 rectl
.xRight
= rectl
.xLeft
+ relDirtyRect
.width
;
5872 rectl
.yTop
= rectl
.yBottom
+ relDirtyRect
.height
;
5874 NPEvent pluginEvent
;
5875 pluginEvent
.event
= WM_PAINT
;
5876 pluginEvent
.wParam
= (uint32
)aHPS
;
5877 pluginEvent
.lParam
= (uint32
)&rectl
;
5878 mInstance
->HandleEvent(&pluginEvent
, nsnull
);
5882 #if defined(MOZ_X11)
5883 void nsPluginInstanceOwner::Paint(gfxContext
* aContext
,
5884 const gfxRect
& aFrameRect
,
5885 const gfxRect
& aDirtyRect
)
5887 if (!mInstance
|| !mObjectFrame
)
5890 #ifdef MOZ_USE_IMAGE_EXPOSE
5891 // through to be able to paint the context passed in. This allows
5892 // us to handle plugins that do not self invalidate (slowly, but
5893 // accurately), and it allows us to reduce flicker.
5894 PRBool simpleImageRender
= PR_FALSE
;
5895 mInstance
->GetValueFromPlugin(NPPVpluginWindowlessLocalBool
,
5896 &simpleImageRender
);
5897 if (simpleImageRender
) {
5898 gfxMatrix matrix
= aContext
->CurrentMatrix();
5899 if (!matrix
.HasNonAxisAlignedTransform())
5905 // to provide crisper and faster drawing.
5906 gfxRect pluginRect
= aFrameRect
;
5907 if (aContext
->UserToDevicePixelSnapped(pluginRect
)) {
5908 pluginRect
= aContext
->DeviceToUser(pluginRect
);
5911 // Round out the dirty rect to plugin pixels to ensure the plugin draws
5912 // enough pixels for interpolation to device pixels.
5913 gfxRect dirtyRect
= aDirtyRect
+ -pluginRect
.pos
;
5914 dirtyRect
.RoundOut();
5916 // Plugins can only draw an integer number of pixels.
5918 // With translation-only transformation matrices, pluginRect is already
5921 // With more complex transformations, modifying the scales in the
5922 // transformation matrix could retain subpixel accuracy and let the plugin
5923 // draw a suitable number of pixels for interpolation to device pixels in
5924 // Renderer::Draw, but such cases are not common enough to warrant the
5926 nsIntSize
pluginSize(NS_lround(pluginRect
.size
.width
),
5927 NS_lround(pluginRect
.size
.height
));
5929 // Determine what the plugin needs to draw.
5930 nsIntRect
pluginDirtyRect(PRInt32(dirtyRect
.pos
.x
),
5931 PRInt32(dirtyRect
.pos
.y
),
5932 PRInt32(dirtyRect
.size
.width
),
5933 PRInt32(dirtyRect
.size
.height
));
5934 if (!pluginDirtyRect
.
5935 IntersectRect(nsIntRect(0, 0, pluginSize
.width
, pluginSize
.height
),
5942 PRUint32 rendererFlags
= 0;
5943 if (!mFlash10Quirks
) {
5945 Renderer::DRAW_SUPPORTS_CLIP_RECT
|
5946 Renderer::DRAW_SUPPORTS_ALTERNATE_VISUAL
;
5950 mInstance
->IsTransparent(&transparent
);
5952 rendererFlags
|= Renderer::DRAW_IS_OPAQUE
;
5954 // Renderer::Draw() draws a rectangle with top-left at the aContext origin.
5955 gfxContextAutoSaveRestore
autoSR(aContext
);
5956 aContext
->Translate(pluginRect
.pos
);
5958 Renderer
renderer(window
, this, pluginSize
, pluginDirtyRect
);
5959 #ifdef MOZ_WIDGET_GTK2
5960 // This is the visual used by the widgets, 24-bit if available.
5961 GdkVisual
* gdkVisual
= gdk_rgb_get_visual();
5962 Visual
* visual
= gdk_x11_visual_get_xvisual(gdkVisual
);
5964 gdk_x11_screen_get_xscreen(gdk_visual_get_screen(gdkVisual
));
5966 #ifdef MOZ_WIDGET_QT
5967 Display
* dpy
= QX11Info().display();
5968 Screen
* screen
= ScreenOfDisplay(dpy
, QX11Info().screen());
5969 Visual
* visual
= static_cast<Visual
*>(QX11Info().visual());
5971 renderer
.Draw(aContext
, nsIntSize(window
->width
, window
->height
),
5972 rendererFlags
, screen
, visual
, nsnull
);
5975 #ifdef MOZ_USE_IMAGE_EXPOSE
5977 static GdkWindow
* GetClosestWindow(nsIDOMElement
*element
)
5979 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(element
);
5980 nsIFrame
* frame
= content
->GetPrimaryFrame();
5984 nsIWidget
* win
= frame
->GetNearestWidget();
5988 GdkWindow
* w
= static_cast<GdkWindow
*>(win
->GetNativeData(NS_NATIVE_WINDOW
));
5993 nsPluginInstanceOwner::ReleaseXShm()
5996 XFreeGC(gdk_x11_get_default_xdisplay(), mXlibSurfGC
);
6000 if (mSharedSegmentInfo
.shmaddr
) {
6001 XShmDetach(gdk_x11_get_default_xdisplay(), &mSharedSegmentInfo
);
6002 shmdt(mSharedSegmentInfo
.shmaddr
);
6003 mSharedSegmentInfo
.shmaddr
= nsnull
;
6006 if (mSharedXImage
) {
6007 XDestroyImage(mSharedXImage
);
6008 mSharedXImage
= nsnull
;
6013 nsPluginInstanceOwner::SetupXShm()
6020 mXlibSurfGC
= XCreateGC(gdk_x11_get_default_xdisplay(),
6027 // we use 16 as the default depth because that is the value of the
6028 // screen, but not the default X default depth.
6030 int foundVisual
= XMatchVisualInfo(gdk_x11_get_default_xdisplay(),
6031 gdk_x11_get_default_screen(),
6038 memset(&mSharedSegmentInfo
, 0, sizeof(XShmSegmentInfo
));
6039 mSharedXImage
= XShmCreateImage(gdk_x11_get_default_xdisplay(),
6044 &mSharedSegmentInfo
,
6046 mPluginSize
.height
);
6050 NS_ASSERTION(mSharedXImage
->height
, "do not call shmget with zero");
6051 mSharedSegmentInfo
.shmid
= shmget(IPC_PRIVATE
,
6052 mSharedXImage
->bytes_per_line
* mSharedXImage
->height
,
6054 if (mSharedSegmentInfo
.shmid
== -1) {
6055 XDestroyImage(mSharedXImage
);
6056 mSharedXImage
= nsnull
;
6060 mSharedXImage
->data
= static_cast<char*>(shmat(mSharedSegmentInfo
.shmid
, 0, 0));
6061 if (mSharedXImage
->data
== (char*) -1) {
6062 shmctl(mSharedSegmentInfo
.shmid
, IPC_RMID
, 0);
6063 XDestroyImage(mSharedXImage
);
6064 mSharedXImage
= nsnull
;
6068 mSharedSegmentInfo
.shmaddr
= mSharedXImage
->data
;
6069 mSharedSegmentInfo
.readOnly
= False
;
6071 Status s
= XShmAttach(gdk_x11_get_default_xdisplay(), &mSharedSegmentInfo
);
6072 XSync(gdk_x11_get_default_xdisplay(), False
);
6073 shmctl(mSharedSegmentInfo
.shmid
, IPC_RMID
, 0);
6075 // attach failed, call shmdt and null shmaddr before calling
6077 shmdt(mSharedSegmentInfo
.shmaddr
);
6078 mSharedSegmentInfo
.shmaddr
= nsnull
;
6089 // This method supports the NPImageExpose API which is specific to the
6090 // HILDON platform. Basically what it allows us to do is to pass a
6091 // memory buffer into a plugin (namely flash), and have flash draw
6092 // directly into the buffer.
6094 // It may be faster if the rest of the system used offscreen image
6095 // surfaces, but right now offscreen surfaces are using X
6096 // surfaces. And because of this, we need to create a new image
6097 // surface and copy that to the passed gfx context.
6099 // This is not ideal and it should not be faster than what a
6100 // windowless plugin can do. However, in A/B testing of flash on the
6101 // N900, this approach is considerably faster.
6103 // Hopefully this API can die off in favor of a more robust plugin API.
6106 nsPluginInstanceOwner::NativeImageDraw(NPRect
* invalidRect
)
6108 // if we haven't been positioned yet, ignore
6112 // if the clip rect is zero, we have nothing to do.
6113 if (NSToIntCeil(mAbsolutePositionClip
.Width()) == 0 ||
6114 NSToIntCeil(mAbsolutePositionClip
.Height()) == 0)
6117 // The flash plugin on Maemo n900 requires the width/height to be
6119 PRInt32 absPosWidth
= NSToIntCeil(mAbsolutePosition
.Width()) / 2 * 2;
6120 PRInt32 absPosHeight
= NSToIntCeil(mAbsolutePosition
.Height()) / 2 * 2;
6122 // if the plugin is hidden, nothing to draw.
6123 if (absPosHeight
== 0 || absPosWidth
== 0)
6126 // Making X or DOM method calls can cause our frame to go
6127 // away, which might kill us...
6128 nsCOMPtr
<nsIPluginInstanceOwner
> kungFuDeathGrip(this);
6130 PRBool sizeChanged
= (mPluginSize
.width
!= absPosWidth
||
6131 mPluginSize
.height
!= absPosHeight
);
6133 if (!mSharedXImage
|| sizeChanged
) {
6134 mPluginSize
= nsIntSize(absPosWidth
, absPosHeight
);
6136 if (NS_FAILED(SetupXShm()))
6142 NS_ASSERTION(window
, "Window can not be null");
6144 // setup window such that it knows about the size and clip. This
6145 // is to work around a flash clipping bug when using the Image
6147 if (!invalidRect
&& sizeChanged
) {
6149 newClipRect
.left
= 0;
6150 newClipRect
.top
= 0;
6151 newClipRect
.right
= window
->width
;
6152 newClipRect
.bottom
= window
->height
;
6154 window
->clipRect
= newClipRect
;
6158 NPSetWindowCallbackStruct
* ws_info
=
6159 static_cast<NPSetWindowCallbackStruct
*>(window
->ws_info
);
6160 ws_info
->visual
= 0;
6161 ws_info
->colormap
= 0;
6162 ws_info
->depth
= 16;
6163 mInstance
->SetWindow(window
);
6166 NPEvent pluginEvent
;
6167 NPImageExpose imageExpose
;
6168 XGraphicsExposeEvent
& exposeEvent
= pluginEvent
.xgraphicsexpose
;
6170 // set the drawing info
6171 exposeEvent
.type
= GraphicsExpose
;
6172 exposeEvent
.display
= 0;
6174 // Store imageExpose structure pointer as drawable member
6175 exposeEvent
.drawable
= (Drawable
)&imageExpose
;
6176 exposeEvent
.count
= 0;
6177 exposeEvent
.serial
= 0;
6178 exposeEvent
.send_event
= False
;
6179 exposeEvent
.major_code
= 0;
6180 exposeEvent
.minor_code
= 0;
6184 exposeEvent
.width
= window
->width
;
6185 exposeEvent
.height
= window
->height
;
6189 imageExpose
.width
= window
->width
;
6190 imageExpose
.height
= window
->height
;
6192 imageExpose
.depth
= 16;
6194 imageExpose
.translateX
= 0;
6195 imageExpose
.translateY
= 0;
6197 if (window
->width
== 0)
6200 float scale
= mAbsolutePosition
.Width() / (float) window
->width
;
6202 imageExpose
.scaleX
= scale
;
6203 imageExpose
.scaleY
= scale
;
6205 imageExpose
.stride
= mPluginSize
.width
* 2;
6206 imageExpose
.data
= mSharedXImage
->data
;
6207 imageExpose
.dataSize
.width
= mPluginSize
.width
;
6208 imageExpose
.dataSize
.height
= mPluginSize
.height
;
6211 memset(mSharedXImage
->data
, 0, mPluginSize
.width
* mPluginSize
.height
* 2);
6213 PRInt16 response
= kNPEventNotHandled
;
6214 mInstance
->HandleEvent(&pluginEvent
, &response
);
6215 if (response
== kNPEventNotHandled
)
6218 // Setup the clip rectangle
6220 rect
.x
= NSToIntFloor(mAbsolutePositionClip
.X());
6221 rect
.y
= NSToIntFloor(mAbsolutePositionClip
.Y());
6222 rect
.width
= NSToIntCeil(mAbsolutePositionClip
.Width());
6223 rect
.height
= NSToIntCeil(mAbsolutePositionClip
.Height());
6225 PRInt32 absPosX
= NSToIntFloor(mAbsolutePosition
.X());
6226 PRInt32 absPosY
= NSToIntFloor(mAbsolutePosition
.Y());
6228 XSetClipRectangles(gdk_x11_get_default_xdisplay(),
6235 XShmPutImage(gdk_x11_get_default_xdisplay(),
6247 XSetClipRectangles(gdk_x11_get_default_xdisplay(), mXlibSurfGC
, 0, 0, nsnull
, 0, Unsorted
);
6249 XFlush(gdk_x11_get_default_xdisplay());
6255 nsPluginInstanceOwner::Renderer::DrawWithXlib(gfxXlibSurface
* xsurface
,
6257 nsIntRect
*clipRects
,
6258 PRUint32 numClipRects
)
6260 Screen
*screen
= cairo_xlib_surface_get_screen(xsurface
->CairoSurface());
6263 if (!xsurface
->GetColormapAndVisual(&colormap
, &visual
)) {
6264 NS_ERROR("Failed to get visual and colormap");
6265 return NS_ERROR_UNEXPECTED
;
6268 nsIPluginInstance
*instance
= mInstanceOwner
->mInstance
;
6270 return NS_ERROR_FAILURE
;
6272 // See if the plugin must be notified of new window parameters.
6273 PRBool doupdatewindow
= PR_FALSE
;
6275 if (mWindow
->x
!= offset
.x
|| mWindow
->y
!= offset
.y
) {
6276 mWindow
->x
= offset
.x
;
6277 mWindow
->y
= offset
.y
;
6278 doupdatewindow
= PR_TRUE
;
6281 if (nsIntSize(mWindow
->width
, mWindow
->height
) != mPluginSize
) {
6282 mWindow
->width
= mPluginSize
.width
;
6283 mWindow
->height
= mPluginSize
.height
;
6284 doupdatewindow
= PR_TRUE
;
6287 // The clip rect is relative to drawable top-left.
6288 NS_ASSERTION(numClipRects
<= 1, "We don't support multiple clip rectangles!");
6291 clipRect
.x
= clipRects
[0].x
;
6292 clipRect
.y
= clipRects
[0].y
;
6293 clipRect
.width
= clipRects
[0].width
;
6294 clipRect
.height
= clipRects
[0].height
;
6295 // NPRect members are unsigned, but clip rectangles should be contained by
6297 NS_ASSERTION(clipRect
.x
>= 0 && clipRect
.y
>= 0,
6298 "Clip rectangle offsets are negative!");
6301 clipRect
.x
= offset
.x
;
6302 clipRect
.y
= offset
.y
;
6303 clipRect
.width
= mWindow
->width
;
6304 clipRect
.height
= mWindow
->height
;
6305 // Don't ask the plugin to draw outside the drawable.
6306 // This also ensures that the unsigned clip rectangle offsets won't be -ve.
6307 gfxIntSize surfaceSize
= xsurface
->GetSize();
6308 clipRect
.IntersectRect(clipRect
,
6310 surfaceSize
.width
, surfaceSize
.height
));
6314 newClipRect
.left
= clipRect
.x
;
6315 newClipRect
.top
= clipRect
.y
;
6316 newClipRect
.right
= clipRect
.XMost();
6317 newClipRect
.bottom
= clipRect
.YMost();
6318 if (mWindow
->clipRect
.left
!= newClipRect
.left
||
6319 mWindow
->clipRect
.top
!= newClipRect
.top
||
6320 mWindow
->clipRect
.right
!= newClipRect
.right
||
6321 mWindow
->clipRect
.bottom
!= newClipRect
.bottom
) {
6322 mWindow
->clipRect
= newClipRect
;
6323 doupdatewindow
= PR_TRUE
;
6326 NPSetWindowCallbackStruct
* ws_info
=
6327 static_cast<NPSetWindowCallbackStruct
*>(mWindow
->ws_info
);
6329 if (ws_info
->visual
!= visual
|| ws_info
->colormap
!= colormap
) {
6330 ws_info
->visual
= visual
;
6331 ws_info
->colormap
= colormap
;
6332 ws_info
->depth
= gfxXlibSurface::DepthOfVisual(screen
, visual
);
6333 doupdatewindow
= PR_TRUE
;
6337 #ifdef MOZ_COMPOSITED_PLUGINS
6338 if (mWindow
->type
== NPWindowTypeDrawable
)
6342 instance
->SetWindow(mWindow
);
6345 // Translate the dirty rect to drawable coordinates.
6346 nsIntRect dirtyRect
= mDirtyRect
+ offset
;
6347 if (mInstanceOwner
->mFlash10Quirks
) {
6348 // Work around a bug in Flash up to 10.1 d51 at least, where expose event
6349 // top left coordinates within the plugin-rect and not at the drawable
6350 // origin are misinterpreted. (We can move the top left coordinate
6351 // provided it is within the clipRect.)
6352 dirtyRect
.SetRect(offset
.x
, offset
.y
,
6353 mDirtyRect
.XMost(), mDirtyRect
.YMost());
6355 // Intersect the dirty rect with the clip rect to ensure that it lies within
6357 if (!dirtyRect
.IntersectRect(dirtyRect
, clipRect
))
6360 #ifdef MOZ_COMPOSITED_PLUGINS
6361 if (mWindow
->type
== NPWindowTypeDrawable
) {
6363 XEvent pluginEvent
= XEvent();
6364 XGraphicsExposeEvent
& exposeEvent
= pluginEvent
.xgraphicsexpose
;
6365 // set the drawing info
6366 exposeEvent
.type
= GraphicsExpose
;
6367 exposeEvent
.display
= DisplayOfScreen(screen
);
6368 exposeEvent
.drawable
= xsurface
->XDrawable();
6369 exposeEvent
.x
= dirtyRect
.x
;
6370 exposeEvent
.y
= dirtyRect
.y
;
6371 exposeEvent
.width
= dirtyRect
.width
;
6372 exposeEvent
.height
= dirtyRect
.height
;
6373 exposeEvent
.count
= 0;
6374 // information not set:
6375 exposeEvent
.serial
= 0;
6376 exposeEvent
.send_event
= False
;
6377 exposeEvent
.major_code
= 0;
6378 exposeEvent
.minor_code
= 0;
6380 instance
->HandleEvent(&pluginEvent
, nsnull
);
6381 #ifdef MOZ_COMPOSITED_PLUGINS
6384 /* XXX: this is very nasty. We need a better way of getting at mPlugWindow */
6385 GtkWidget
*plug
= (GtkWidget
*)(((nsPluginNativeWindow
*)mWindow
)->mPlugWindow
);
6386 //GtkWidget *plug = (GtkWidget*)(((nsPluginNativeWindowGtk2*)mWindow)->mSocketWidget);
6388 /* Cairo has bugs with IncludeInferiors when using paint
6389 * so we use XCopyArea directly instead. */
6391 gcv
.subwindow_mode
= IncludeInferiors
;
6392 gcv
.graphics_exposures
= False
;
6393 Drawable drawable
= xsurface
->XDrawable();
6394 GC gc
= XCreateGC(DefaultXDisplay(), drawable
, GCGraphicsExposures
| GCSubwindowMode
, &gcv
);
6395 /* The source and destination appear to always line up, so src and dest
6396 * coords should be the same */
6397 XCopyArea(DefaultXDisplay(), gdk_x11_drawable_get_xid(plug
->window
),
6406 XFreeGC(DefaultXDisplay(), gc
);
6413 void nsPluginInstanceOwner::SendIdleEvent()
6415 #ifdef MAC_CARBON_PLUGINS
6416 // validate the plugin clipping information by syncing the plugin window info to
6417 // reflect the current widget location. This makes sure that everything is updated
6418 // correctly in the event of scrolling in the window.
6420 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
6421 if (pluginWidget
&& NS_SUCCEEDED(pluginWidget
->StartDrawPlugin())) {
6422 void* window
= FixUpPluginWindow(ePluginPaintEnable
);
6424 EventRecord idleEvent
;
6425 InitializeEventRecord(&idleEvent
, nsnull
);
6426 idleEvent
.what
= nullEvent
;
6428 // give a bogus 'where' field of our null event when hidden, so Flash
6429 // won't respond to mouse moves in other tabs, see bug 120875
6430 if (!mWidgetVisible
)
6431 idleEvent
.where
.h
= idleEvent
.where
.v
= 20000;
6433 mInstance
->HandleEvent(&idleEvent
, nsnull
);
6436 pluginWidget
->EndDrawPlugin();
6442 #ifdef MAC_CARBON_PLUGINS
6443 void nsPluginInstanceOwner::StartTimer(PRBool isVisible
)
6445 if (GetEventModel() != NPEventModelCarbon
)
6448 mPluginHost
->AddIdleTimeTarget(this, isVisible
);
6451 void nsPluginInstanceOwner::CancelTimer()
6453 mPluginHost
->RemoveIdleTimeTarget(this);
6457 nsresult
nsPluginInstanceOwner::Init(nsPresContext
* aPresContext
,
6458 nsObjectFrame
* aFrame
,
6459 nsIContent
* aContent
)
6461 mLastEventloopNestingLevel
= GetEventloopNestingLevel();
6463 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
6464 ("nsPluginInstanceOwner::Init() called on %p for frame %p\n", this,
6467 mObjectFrame
= aFrame
;
6468 mContent
= aContent
;
6470 nsWeakFrame
weakFrame(aFrame
);
6472 // Some plugins require a specific sequence of shutdown and startup when
6473 // a page is reloaded. Shutdown happens usually when the last instance
6474 // is destroyed. Here we make sure the plugin instance in the old
6475 // document is destroyed before we try to create the new one.
6476 aPresContext
->EnsureVisible();
6478 if (!weakFrame
.IsAlive()) {
6479 PR_LOG(nsObjectFrameLM
, PR_LOG_DEBUG
,
6480 ("nsPluginInstanceOwner::Init's EnsureVisible() call destroyed "
6481 "instance owner %p\n", this));
6483 return NS_ERROR_NOT_AVAILABLE
;
6486 // register context menu listener
6487 mCXMenuListener
= new nsPluginDOMContextMenuListener();
6488 if (mCXMenuListener
) {
6489 mCXMenuListener
->Init(aContent
);
6492 nsCOMPtr
<nsIDOMEventTarget
> target(do_QueryInterface(mContent
));
6495 nsCOMPtr
<nsIDOMEventListener
> listener
;
6496 QueryInterface(NS_GET_IID(nsIDOMEventListener
), getter_AddRefs(listener
));
6498 // Register focus listener
6499 mContent
->AddEventListenerByIID(listener
, NS_GET_IID(nsIDOMFocusListener
));
6501 // Register mouse listener
6502 mContent
->AddEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseListener
));
6504 // now do the mouse motion listener
6505 mContent
->AddEventListenerByIID(listener
, NS_GET_IID(nsIDOMMouseMotionListener
));
6507 // Register key listener
6508 target
->AddEventListener(NS_LITERAL_STRING("keypress"), listener
, PR_TRUE
);
6509 target
->AddEventListener(NS_LITERAL_STRING("keydown"), listener
, PR_TRUE
);
6510 target
->AddEventListener(NS_LITERAL_STRING("keyup"), listener
, PR_TRUE
);
6512 // Register drag listener
6513 target
->AddEventListener(NS_LITERAL_STRING("drop"), listener
, PR_TRUE
);
6514 target
->AddEventListener(NS_LITERAL_STRING("dragdrop"), listener
, PR_TRUE
);
6515 target
->AddEventListener(NS_LITERAL_STRING("drag"), listener
, PR_TRUE
);
6516 target
->AddEventListener(NS_LITERAL_STRING("dragenter"), listener
, PR_TRUE
);
6517 target
->AddEventListener(NS_LITERAL_STRING("dragover"), listener
, PR_TRUE
);
6518 target
->AddEventListener(NS_LITERAL_STRING("dragleave"), listener
, PR_TRUE
);
6519 target
->AddEventListener(NS_LITERAL_STRING("dragexit"), listener
, PR_TRUE
);
6520 target
->AddEventListener(NS_LITERAL_STRING("dragstart"), listener
, PR_TRUE
);
6521 target
->AddEventListener(NS_LITERAL_STRING("draggesture"), listener
, PR_TRUE
);
6522 target
->AddEventListener(NS_LITERAL_STRING("dragend"), listener
, PR_TRUE
);
6525 // Register scroll position listeners
6526 // We need to register a scroll position listener on every scrollable
6527 // frame up to the top
6528 for (nsIFrame
* f
= mObjectFrame
; f
; f
= nsLayoutUtils::GetCrossDocParentFrame(f
)) {
6529 nsIScrollableFrame
* sf
= do_QueryFrame(f
);
6531 sf
->AddScrollPositionListener(this);
6538 void* nsPluginInstanceOwner::GetPluginPortFromWidget()
6540 //!!! Port must be released for windowless plugins on Windows, because it is HDC !!!
6542 void* result
= NULL
;
6545 if (mPluginWindow
&& (mPluginWindow
->type
== NPWindowTypeDrawable
))
6546 result
= mWidget
->GetNativeData(NS_NATIVE_GRAPHIC
);
6550 if (GetDrawingModel() == NPDrawingModelCoreGraphics
||
6551 GetDrawingModel() == NPDrawingModelCoreAnimation
||
6552 GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation
)
6553 result
= mWidget
->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG
);
6556 result
= mWidget
->GetNativeData(NS_NATIVE_PLUGIN_PORT
);
6561 void nsPluginInstanceOwner::ReleasePluginPort(void * pluginPort
)
6564 if (mWidget
&& mPluginWindow
&&
6565 mPluginWindow
->type
== NPWindowTypeDrawable
) {
6566 mWidget
->FreeNativeData((HDC
)pluginPort
, NS_NATIVE_GRAPHIC
);
6571 NS_IMETHODIMP
nsPluginInstanceOwner::CreateWidget(void)
6573 NS_ENSURE_TRUE(mPluginWindow
, NS_ERROR_NULL_POINTER
);
6575 nsresult rv
= NS_ERROR_FAILURE
;
6579 PRBool windowless
= PR_FALSE
;
6580 mInstance
->IsWindowless(&windowless
);
6582 // always create widgets in Twips, not pixels
6583 nsPresContext
* context
= mObjectFrame
->PresContext();
6584 rv
= mObjectFrame
->CreateWidget(context
->DevPixelsToAppUnits(mPluginWindow
->width
),
6585 context
->DevPixelsToAppUnits(mPluginWindow
->height
),
6588 mWidget
= mObjectFrame
->GetWidget();
6590 if (PR_TRUE
== windowless
) {
6591 mPluginWindow
->type
= NPWindowTypeDrawable
;
6593 // this needs to be a HDC according to the spec, but I do
6594 // not see the right way to release it so let's postpone
6595 // passing HDC till paint event when it is really
6596 // needed. Change spec?
6597 mPluginWindow
->window
= nsnull
;
6599 // Fill in the display field.
6600 NPSetWindowCallbackStruct
* ws_info
=
6601 static_cast<NPSetWindowCallbackStruct
*>(mPluginWindow
->ws_info
);
6602 ws_info
->display
= DefaultXDisplay();
6604 nsCAutoString description
;
6605 GetPluginDescription(description
);
6606 NS_NAMED_LITERAL_CSTRING(flash10Head
, "Shockwave Flash 10.");
6607 mFlash10Quirks
= StringBeginsWith(description
, flash10Head
);
6610 // Changing to windowless mode changes the NPWindow geometry.
6611 mObjectFrame
->FixupWindow(mObjectFrame
->GetContentRect().Size());
6612 } else if (mWidget
) {
6613 nsIWidget
* parent
= mWidget
->GetParent();
6614 NS_ASSERTION(parent
, "Plugin windows must not be toplevel");
6615 // Set the plugin window to have an empty cliprect. The cliprect
6616 // will be reset when nsRootPresContext::UpdatePluginGeometry
6617 // runs later. The plugin window does need to have the correct
6618 // size here. GetEmptyClipConfiguration will probably give it the
6619 // size, but just in case we haven't been reflowed or something, set
6620 // the size explicitly.
6621 nsAutoTArray
<nsIWidget::Configuration
,1> configuration
;
6622 mObjectFrame
->GetEmptyClipConfiguration(&configuration
);
6623 if (configuration
.Length() > 0) {
6624 configuration
[0].mBounds
.width
= mPluginWindow
->width
;
6625 configuration
[0].mBounds
.height
= mPluginWindow
->height
;
6627 parent
->ConfigureChildren(configuration
);
6629 // mPluginWindow->type is used in |GetPluginPort| so it must
6630 // be initialized first
6631 mPluginWindow
->type
= NPWindowTypeWindow
;
6632 mPluginWindow
->window
= GetPluginPortFromWidget();
6634 #ifdef MAC_CARBON_PLUGINS
6635 // start the idle timer.
6636 StartTimer(PR_TRUE
);
6639 // tell the plugin window about the widget
6640 mPluginWindow
->SetPluginWidget(mWidget
);
6642 // tell the widget about the current plugin instance owner.
6643 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
6645 pluginWidget
->SetPluginInstanceOwner(this);
6654 void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost
* aHost
)
6656 mPluginHost
= aHost
;
6659 #ifdef MOZ_USE_IMAGE_EXPOSE
6660 PRBool
nsPluginInstanceOwner::UpdateVisibility(PRBool aVisible
)
6662 // NOTE: Death grip must be held by caller.
6666 NPEvent pluginEvent
;
6667 XVisibilityEvent
& visibilityEvent
= pluginEvent
.xvisibility
;
6668 visibilityEvent
.type
= VisibilityNotify
;
6669 visibilityEvent
.display
= 0;
6670 visibilityEvent
.state
= aVisible
? VisibilityUnobscured
: VisibilityFullyObscured
;
6671 mInstance
->HandleEvent(&pluginEvent
, nsnull
);
6673 mWidgetVisible
= PR_TRUE
;
6678 // Mac specific code to fix up the port location and clipping region
6681 void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState
)
6683 if (!mWidget
|| !mPluginWindow
|| !mInstance
|| !mObjectFrame
)
6686 NPDrawingModel drawingModel
= GetDrawingModel();
6687 NPEventModel eventModel
= GetEventModel();
6689 nsCOMPtr
<nsIPluginWidget
> pluginWidget
= do_QueryInterface(mWidget
);
6693 // If we've already set up a CGContext in nsObjectFrame::PaintPlugin(), we
6694 // don't want calls to SetPluginPortAndDetectChange() to step on our work.
6695 void* pluginPort
= nsnull
;
6696 if (mInCGPaintLevel
> 0) {
6697 pluginPort
= mPluginWindow
->window
;
6699 pluginPort
= SetPluginPortAndDetectChange();
6702 #ifdef MAC_CARBON_PLUGINS
6703 if (eventModel
== NPEventModelCarbon
&& !pluginPort
)
6707 // We'll need the top-level Cocoa window for the Cocoa event model.
6708 void* cocoaTopLevelWindow
= nsnull
;
6709 if (eventModel
== NPEventModelCocoa
) {
6710 nsIWidget
* widget
= mObjectFrame
->GetNearestWidget();
6713 cocoaTopLevelWindow
= widget
->GetNativeData(NS_NATIVE_WINDOW
);
6714 if (!cocoaTopLevelWindow
)
6718 nsIntPoint pluginOrigin
;
6719 nsIntRect widgetClip
;
6720 PRBool widgetVisible
;
6721 pluginWidget
->GetPluginClipRect(widgetClip
, pluginOrigin
, widgetVisible
);
6722 mWidgetVisible
= widgetVisible
;
6724 // printf("GetPluginClipRect returning visible %d\n", widgetVisible);
6726 #ifndef NP_NO_QUICKDRAW
6727 // set the port coordinates
6728 if (drawingModel
== NPDrawingModelQuickDraw
) {
6729 mPluginWindow
->x
= -static_cast<NP_Port
*>(pluginPort
)->portx
;
6730 mPluginWindow
->y
= -static_cast<NP_Port
*>(pluginPort
)->porty
;
6732 else if (drawingModel
== NPDrawingModelCoreGraphics
||
6733 drawingModel
== NPDrawingModelCoreAnimation
||
6734 drawingModel
== NPDrawingModelInvalidatingCoreAnimation
)
6737 // This would be a lot easier if we could use obj-c here,
6738 // but we can't. Since we have only nsIWidget and we can't
6739 // use its native widget (an obj-c object) we have to go
6740 // from the widget's screen coordinates to its window coords
6741 // instead of straight to window coords.
6742 nsIntPoint geckoScreenCoords
= mWidget
->WidgetToScreenOffset();
6745 #ifndef NP_NO_CARBON
6746 if (eventModel
== NPEventModelCarbon
)
6747 NS_NPAPI_CarbonWindowFrame(static_cast<WindowRef
>(static_cast<NP_CGContext
*>(pluginPort
)->window
), windowRect
);
6751 NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow
, windowRect
);
6754 mPluginWindow
->x
= geckoScreenCoords
.x
- windowRect
.x
;
6755 mPluginWindow
->y
= geckoScreenCoords
.y
- windowRect
.y
;
6758 NPRect oldClipRect
= mPluginWindow
->clipRect
;
6760 // fix up the clipping region
6761 mPluginWindow
->clipRect
.top
= widgetClip
.y
;
6762 mPluginWindow
->clipRect
.left
= widgetClip
.x
;
6764 if (!mWidgetVisible
|| inPaintState
== ePluginPaintDisable
) {
6765 mPluginWindow
->clipRect
.bottom
= mPluginWindow
->clipRect
.top
;
6766 mPluginWindow
->clipRect
.right
= mPluginWindow
->clipRect
.left
;
6768 else if (inPaintState
== ePluginPaintEnable
)
6770 mPluginWindow
->clipRect
.bottom
= mPluginWindow
->clipRect
.top
+ widgetClip
.height
;
6771 mPluginWindow
->clipRect
.right
= mPluginWindow
->clipRect
.left
+ widgetClip
.width
;
6774 // if the clip rect changed, call SetWindow()
6775 // (RealPlayer needs this to draw correctly)
6776 if (mPluginWindow
->clipRect
.left
!= oldClipRect
.left
||
6777 mPluginWindow
->clipRect
.top
!= oldClipRect
.top
||
6778 mPluginWindow
->clipRect
.right
!= oldClipRect
.right
||
6779 mPluginWindow
->clipRect
.bottom
!= oldClipRect
.bottom
)
6781 mInstance
->SetWindow(mPluginWindow
);
6782 mPluginPortChanged
= PR_FALSE
;
6783 #ifdef MAC_CARBON_PLUGINS
6784 // if the clipRect is of size 0, make the null timer fire less often
6786 if (mPluginWindow
->clipRect
.left
== mPluginWindow
->clipRect
.right
||
6787 mPluginWindow
->clipRect
.top
== mPluginWindow
->clipRect
.bottom
) {
6788 StartTimer(PR_FALSE
);
6791 StartTimer(PR_TRUE
);
6794 } else if (mPluginPortChanged
) {
6795 mInstance
->SetWindow(mPluginWindow
);
6796 mPluginPortChanged
= PR_FALSE
;
6799 // After the first NPP_SetWindow call we need to send an initial
6800 // top-level window focus event.
6801 if (eventModel
== NPEventModelCocoa
&& !mSentInitialTopLevelWindowEvent
) {
6802 // Set this before calling ProcessEvent to avoid endless recursion.
6803 mSentInitialTopLevelWindowEvent
= PR_TRUE
;
6805 nsGUIEvent
pluginEvent(PR_TRUE
, NS_NON_RETARGETED_PLUGIN_EVENT
, nsnull
);
6806 NPCocoaEvent cocoaEvent
;
6807 InitializeNPCocoaEvent(&cocoaEvent
);
6808 cocoaEvent
.type
= NPCocoaEventWindowFocusChanged
;
6809 cocoaEvent
.data
.focus
.hasFocus
= NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow
);
6810 pluginEvent
.pluginEvent
= &cocoaEvent
;
6811 ProcessEvent(pluginEvent
);
6814 #ifndef NP_NO_QUICKDRAW
6815 if (drawingModel
== NPDrawingModelQuickDraw
)
6816 return ::GetWindowFromPort(static_cast<NP_Port
*>(pluginPort
)->port
);
6819 #ifdef MAC_CARBON_PLUGINS
6820 if (drawingModel
== NPDrawingModelCoreGraphics
&& eventModel
== NPEventModelCarbon
)
6821 return static_cast<NP_CGContext
*>(pluginPort
)->window
;
6828 nsPluginInstanceOwner::HidePluginWindow()
6830 if (!mPluginWindow
|| !mInstance
) {
6834 mPluginWindow
->clipRect
.bottom
= mPluginWindow
->clipRect
.top
;
6835 mPluginWindow
->clipRect
.right
= mPluginWindow
->clipRect
.left
;
6836 mWidgetVisible
= PR_FALSE
;
6837 mInstance
->SetWindow(mPluginWindow
);
6842 void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(PRBool aSetWindow
)
6847 // For windowless plugins a non-empty clip rectangle will be
6848 // passed to the plugin during paint, an additional update
6849 // of the the clip rectangle here is not required
6850 if (aSetWindow
&& !mWidget
&& mPluginWindowVisible
&& !UseAsyncRendering())
6853 const NPWindow oldWindow
= *mPluginWindow
;
6855 PRBool windowless
= (mPluginWindow
->type
== NPWindowTypeDrawable
);
6856 nsIntPoint origin
= mObjectFrame
->GetWindowOriginInPixels(windowless
);
6858 mPluginWindow
->x
= origin
.x
;
6859 mPluginWindow
->y
= origin
.y
;
6861 mPluginWindow
->clipRect
.left
= 0;
6862 mPluginWindow
->clipRect
.top
= 0;
6864 if (mPluginWindowVisible
) {
6865 mPluginWindow
->clipRect
.right
= mPluginWindow
->width
;
6866 mPluginWindow
->clipRect
.bottom
= mPluginWindow
->height
;
6868 mPluginWindow
->clipRect
.right
= 0;
6869 mPluginWindow
->clipRect
.bottom
= 0;
6875 if (mPluginWindow
->x
!= oldWindow
.x
||
6876 mPluginWindow
->y
!= oldWindow
.y
||
6877 mPluginWindow
->clipRect
.left
!= oldWindow
.clipRect
.left
||
6878 mPluginWindow
->clipRect
.top
!= oldWindow
.clipRect
.top
||
6879 mPluginWindow
->clipRect
.right
!= oldWindow
.clipRect
.right
||
6880 mPluginWindow
->clipRect
.bottom
!= oldWindow
.clipRect
.bottom
) {
6886 nsPluginInstanceOwner::CallSetWindow()
6891 if (UseAsyncRendering()) {
6892 mInstance
->AsyncSetWindow(mPluginWindow
);
6894 mInstance
->SetWindow(mPluginWindow
);
6899 nsPluginInstanceOwner::UpdateWindowVisibility(PRBool aVisible
)
6901 mPluginWindowVisible
= aVisible
;
6902 UpdateWindowPositionAndClipRect(PR_TRUE
);
6907 // Little helper function to resolve relative URL in
6908 // |value| for certain inputs of |name|
6909 void nsPluginInstanceOwner::FixUpURLS(const nsString
&name
, nsAString
&value
)
6911 if (name
.LowerCaseEqualsLiteral("pluginurl") ||
6912 name
.LowerCaseEqualsLiteral("pluginspage")) {
6914 nsCOMPtr
<nsIURI
> baseURI
= mContent
->GetBaseURI();
6915 nsAutoString newURL
;
6916 NS_MakeAbsoluteURI(newURL
, value
, baseURI
);
6917 if (!newURL
.IsEmpty())
6922 #ifdef MOZ_USE_IMAGE_EXPOSE
6924 nsPluginInstanceOwner::SetAbsoluteScreenPosition(nsIDOMElement
* element
,
6925 nsIDOMClientRect
* position
,
6926 nsIDOMClientRect
* clip
)
6928 if (!element
|| !position
|| !clip
)
6929 return NS_ERROR_FAILURE
;
6931 // Making X or DOM method calls can cause our frame to go
6932 // away, which might kill us...
6933 nsCOMPtr
<nsIPluginInstanceOwner
> kungFuDeathGrip(this);
6936 mBlitWindow
= GDK_WINDOW_XWINDOW(GetClosestWindow(element
));
6938 return NS_ERROR_FAILURE
;
6941 float left
, top
, width
, height
;
6942 position
->GetLeft(&left
);
6943 position
->GetTop(&top
);
6944 position
->GetWidth(&width
);
6945 position
->GetHeight(&height
);
6947 mAbsolutePosition
= gfxRect(left
, top
, width
, height
);
6949 clip
->GetLeft(&left
);
6951 clip
->GetWidth(&width
);
6952 clip
->GetHeight(&height
);
6954 mAbsolutePositionClip
= gfxRect(left
, top
, width
, height
);
6956 UpdateVisibility(!(width
== 0 && height
== 0));
6961 PRBool simpleImageRender
= PR_FALSE
;
6962 mInstance
->GetValueFromPlugin(NPPVpluginWindowlessLocalBool
,
6963 &simpleImageRender
);
6964 if (simpleImageRender
)