2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
// vim:set ts=2 sts=2 sw=2 et cin:
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
|
|
|
* Jacek Piskozub <piskozub@iopan.gda.pl>
|
|
|
|
* Leon Sha <leon.sha@sun.com>
|
|
|
|
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
|
|
|
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
|
|
|
* Christian Biesinger <cbiesinger@web.de>
|
2007-03-26 18:07:57 -07:00
|
|
|
* Josh Aas <josh@mozilla.com>
|
2008-03-25 09:56:04 -07:00
|
|
|
* Mats Palmgren <mats.palmgren@bredband.net>
|
2007-03-22 10:30:00 -07:00
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
|
|
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
/* rendering objects for replaced elements implemented by a plugin */
|
|
|
|
|
|
|
|
#include "nscore.h"
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsPresContext.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
#include "nsIView.h"
|
|
|
|
#include "nsIViewManager.h"
|
|
|
|
#include "nsIDOMKeyListener.h"
|
2008-10-17 13:04:55 -07:00
|
|
|
#include "nsIDOMDragEvent.h"
|
2008-08-09 06:43:08 -07:00
|
|
|
#ifdef MOZ_X11
|
|
|
|
#ifdef MOZ_WIDGET_QT
|
|
|
|
#include <QWidget>
|
|
|
|
#include <QX11Info>
|
|
|
|
#endif
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIPluginHost.h"
|
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "prmem.h"
|
|
|
|
#include "nsGkAtoms.h"
|
2007-03-22 16:04:51 -07:00
|
|
|
#include "nsIAppShell.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsINodeInfo.h"
|
|
|
|
#include "nsIURL.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsIPluginInstanceOwner.h"
|
2009-06-29 22:55:05 -07:00
|
|
|
#include "nsIPluginInstance.h"
|
|
|
|
#include "nsIPluginTagInfo.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "plstr.h"
|
|
|
|
#include "nsILinkHandler.h"
|
|
|
|
#include "nsIEventListener.h"
|
|
|
|
#include "nsIScrollableView.h"
|
|
|
|
#include "nsIScrollPositionListener.h"
|
|
|
|
#include "nsITimer.h"
|
|
|
|
#include "nsIDocShellTreeItem.h"
|
|
|
|
#include "nsIDocShellTreeOwner.h"
|
|
|
|
#include "nsDocShellCID.h"
|
|
|
|
#include "nsIWebBrowserChrome.h"
|
|
|
|
#include "nsIDOMElement.h"
|
|
|
|
#include "nsIDOMNodeList.h"
|
|
|
|
#include "nsIDOMHTMLObjectElement.h"
|
|
|
|
#include "nsIDOMHTMLEmbedElement.h"
|
|
|
|
#include "nsIDOMHTMLAppletElement.h"
|
|
|
|
#include "nsIDOMWindow.h"
|
|
|
|
#include "nsIDOMDocumentEvent.h"
|
|
|
|
#include "nsIDOMMouseListener.h"
|
|
|
|
#include "nsIDOMMouseMotionListener.h"
|
|
|
|
#include "nsIDOMFocusListener.h"
|
|
|
|
#include "nsIDOMContextMenuListener.h"
|
2007-05-14 02:11:38 -07:00
|
|
|
#include "nsIDOMEventTarget.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIDOMNSEvent.h"
|
|
|
|
#include "nsIPrivateDOMEvent.h"
|
|
|
|
#include "nsIDocumentEncoder.h"
|
|
|
|
#include "nsXPIDLString.h"
|
|
|
|
#include "nsIDOMRange.h"
|
|
|
|
#include "nsIPluginWidget.h"
|
|
|
|
#include "nsGUIEvent.h"
|
|
|
|
#include "nsIRenderingContext.h"
|
|
|
|
#include "npapi.h"
|
|
|
|
#include "nsTransform2D.h"
|
|
|
|
#include "nsIImageLoadingContent.h"
|
|
|
|
#include "nsIObjectLoadingContent.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsDisplayList.h"
|
|
|
|
#include "nsAttrName.h"
|
|
|
|
#include "nsDataHashtable.h"
|
2008-03-14 16:08:57 -07:00
|
|
|
#include "nsDOMClassInfo.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
#include "nsFocusManager.h"
|
2009-07-21 17:44:57 -07:00
|
|
|
#include "nsLayoutUtils.h"
|
2009-07-21 17:45:00 -07:00
|
|
|
#include "nsFrameManager.h"
|
|
|
|
#include "nsComponentManagerUtils.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// headers for plugin scriptability
|
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
#include "nsIScriptContext.h"
|
|
|
|
#include "nsIXPConnect.h"
|
|
|
|
#include "nsIXPCScriptable.h"
|
|
|
|
#include "nsIClassInfo.h"
|
|
|
|
|
|
|
|
#include "nsObjectFrame.h"
|
|
|
|
#include "nsIObjectFrame.h"
|
|
|
|
#include "nsPluginNativeWindow.h"
|
|
|
|
#include "nsIPluginDocument.h"
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
#include "nsThreadUtils.h"
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "gfxContext.h"
|
|
|
|
|
2008-02-13 22:27:51 -08:00
|
|
|
#ifdef XP_WIN
|
|
|
|
#include "gfxWindowsNativeDrawing.h"
|
2008-10-29 22:28:25 -07:00
|
|
|
#include "gfxWindowsSurface.h"
|
2008-02-13 22:27:51 -08:00
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// accessibility support
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
#include "nsIAccessibilityService.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MOZ_LOGGING
|
|
|
|
#define FORCE_PR_LOG 1 /* Allow logging in the release build */
|
|
|
|
#endif /* MOZ_LOGGING */
|
|
|
|
#include "prlog.h"
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "nsContentCID.h"
|
|
|
|
static NS_DEFINE_CID(kRangeCID, NS_RANGE_CID);
|
2008-03-25 09:56:04 -07:00
|
|
|
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-02-20 03:33:27 -08:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
#include "gfxQuartzNativeDrawing.h"
|
2009-08-26 17:29:47 -07:00
|
|
|
#include "nsPluginUtilsOSX.h"
|
2008-02-20 03:33:27 -08:00
|
|
|
#endif
|
|
|
|
|
2007-07-02 20:33:13 -07:00
|
|
|
#ifdef MOZ_X11
|
|
|
|
#include <X11/Xlib.h>
|
2007-03-22 10:30:00 -07:00
|
|
|
/* X headers suck */
|
2007-07-02 20:33:13 -07:00
|
|
|
enum { XKeyPress = KeyPress };
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifdef KeyPress
|
|
|
|
#undef KeyPress
|
|
|
|
#endif
|
2009-02-25 07:25:12 -08:00
|
|
|
|
|
|
|
#ifdef MOZ_PLATFORM_HILDON
|
|
|
|
#define MOZ_COMPOSITED_PLUGINS 1
|
|
|
|
#endif
|
|
|
|
|
2007-07-02 20:33:13 -07:00
|
|
|
#ifdef MOZ_WIDGET_GTK2
|
2009-01-02 23:37:52 -08:00
|
|
|
#include <gdk/gdk.h>
|
2007-07-02 20:33:13 -07:00
|
|
|
#include <gdk/gdkx.h>
|
2009-02-25 07:25:12 -08:00
|
|
|
#include <gtk/gtk.h>
|
2007-07-02 20:33:13 -07:00
|
|
|
#endif
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-08-06 13:48:55 -07:00
|
|
|
#ifdef MOZ_WIDGET_GTK2
|
|
|
|
#include "gfxGdkNativeRenderer.h"
|
|
|
|
#endif
|
|
|
|
|
2008-08-09 06:43:08 -07:00
|
|
|
#ifdef MOZ_WIDGET_QT
|
|
|
|
#include "gfxQtNativeRenderer.h"
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifdef XP_WIN
|
|
|
|
#include <wtypes.h>
|
|
|
|
#include <winuser.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef CreateEvent // Thank you MS.
|
|
|
|
#undef CreateEvent
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef PR_LOGGING
|
|
|
|
static PRLogModuleInfo *nsObjectFrameLM = PR_NewLogModule("nsObjectFrame");
|
|
|
|
#endif /* PR_LOGGING */
|
|
|
|
|
|
|
|
// 1020 / 60
|
|
|
|
#define NORMAL_PLUGIN_DELAY 17
|
|
|
|
|
|
|
|
// low enough to avoid audio skipping/delays
|
|
|
|
#define HIDDEN_PLUGIN_DELAY 100
|
|
|
|
|
|
|
|
// special class for handeling DOM context menu events because for
|
|
|
|
// some reason it starves other mouse events if implemented on the
|
|
|
|
// same class
|
|
|
|
class nsPluginDOMContextMenuListener : public nsIDOMContextMenuListener,
|
|
|
|
public nsIEventListener
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
nsPluginDOMContextMenuListener();
|
|
|
|
virtual ~nsPluginDOMContextMenuListener();
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
NS_IMETHOD ContextMenu(nsIDOMEvent* aContextMenuEvent);
|
|
|
|
|
|
|
|
nsresult Init(nsIContent* aContent);
|
|
|
|
nsresult Destroy(nsIContent* aContent);
|
|
|
|
|
|
|
|
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
nsEventStatus ProcessEvent(const nsGUIEvent& anEvent)
|
|
|
|
{
|
|
|
|
return nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class nsPluginInstanceOwner : public nsIPluginInstanceOwner,
|
2009-07-01 17:54:18 -07:00
|
|
|
public nsIPluginTagInfo,
|
2007-03-22 10:30:00 -07:00
|
|
|
public nsIEventListener,
|
|
|
|
public nsITimerCallback,
|
|
|
|
public nsIDOMMouseListener,
|
|
|
|
public nsIDOMMouseMotionListener,
|
|
|
|
public nsIDOMKeyListener,
|
|
|
|
public nsIDOMFocusListener,
|
2008-10-17 13:04:55 -07:00
|
|
|
public nsIScrollPositionListener
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
nsPluginInstanceOwner();
|
|
|
|
virtual ~nsPluginInstanceOwner();
|
|
|
|
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
//nsIPluginInstanceOwner interface
|
|
|
|
|
|
|
|
NS_IMETHOD SetInstance(nsIPluginInstance *aInstance);
|
|
|
|
|
|
|
|
NS_IMETHOD GetInstance(nsIPluginInstance *&aInstance);
|
|
|
|
|
|
|
|
NS_IMETHOD GetWindow(nsPluginWindow *&aWindow);
|
|
|
|
|
|
|
|
NS_IMETHOD GetMode(nsPluginMode *aMode);
|
|
|
|
|
|
|
|
NS_IMETHOD CreateWidget(void);
|
|
|
|
|
|
|
|
NS_IMETHOD GetURL(const char *aURL, const char *aTarget, void *aPostData,
|
|
|
|
PRUint32 aPostDataLen, void *aHeadersData,
|
|
|
|
PRUint32 aHeadersDataLen, PRBool isFile = PR_FALSE);
|
|
|
|
|
|
|
|
NS_IMETHOD ShowStatus(const char *aStatusMsg);
|
|
|
|
|
|
|
|
NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
|
|
|
|
|
|
|
|
NS_IMETHOD GetDocument(nsIDocument* *aDocument);
|
|
|
|
|
|
|
|
NS_IMETHOD InvalidateRect(nsPluginRect *invalidRect);
|
|
|
|
|
|
|
|
NS_IMETHOD InvalidateRegion(nsPluginRegion invalidRegion);
|
|
|
|
|
|
|
|
NS_IMETHOD ForceRedraw();
|
|
|
|
|
2009-06-29 11:53:52 -07:00
|
|
|
NS_IMETHOD GetNetscapeWindow(void *value);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
NPError ShowNativeContextMenu(NPMenu* menu, nsPluginEvent* event);
|
|
|
|
|
|
|
|
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
|
|
|
double *destX, double *destY, NPCoordinateSpace destSpace);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//nsIPluginTagInfo interface
|
|
|
|
|
|
|
|
NS_IMETHOD GetAttributes(PRUint16& n, const char*const*& names,
|
|
|
|
const char*const*& values);
|
|
|
|
|
|
|
|
NS_IMETHOD GetAttribute(const char* name, const char* *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetTagType(nsPluginTagType *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetTagText(const char* *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetParameters(PRUint16& n, const char*const*& names, const char*const*& values);
|
|
|
|
|
|
|
|
NS_IMETHOD GetParameter(const char* name, const char* *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetDocumentBase(const char* *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetDocumentEncoding(const char* *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetAlignment(const char* *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetWidth(PRUint32 *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetHeight(PRUint32 *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetBorderVertSpace(PRUint32 *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetBorderHorizSpace(PRUint32 *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetUniqueID(PRUint32 *result);
|
|
|
|
|
|
|
|
NS_IMETHOD GetDOMElement(nsIDOMElement* *result);
|
|
|
|
|
2008-08-25 22:36:17 -07:00
|
|
|
// nsIDOMMouseListener interfaces
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent);
|
|
|
|
NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent);
|
|
|
|
NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent);
|
|
|
|
NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent);
|
|
|
|
NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent);
|
|
|
|
NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent);
|
|
|
|
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
|
|
|
|
2008-08-25 18:47:33 -07:00
|
|
|
// nsIDOMMouseMotionListener interfaces
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
|
|
|
|
NS_IMETHOD DragMove(nsIDOMEvent* aMouseEvent) { return NS_OK; }
|
|
|
|
|
|
|
|
// nsIDOMKeyListener interfaces
|
|
|
|
NS_IMETHOD KeyDown(nsIDOMEvent* aKeyEvent);
|
|
|
|
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
|
|
|
|
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
|
|
|
|
|
|
|
|
// nsIDOMFocuListener interfaces
|
|
|
|
NS_IMETHOD Focus(nsIDOMEvent * aFocusEvent);
|
|
|
|
NS_IMETHOD Blur(nsIDOMEvent * aFocusEvent);
|
2008-08-25 22:36:17 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult Destroy();
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
void PrepareToStop(PRBool aDelayedStop);
|
|
|
|
|
2008-08-25 22:36:17 -07:00
|
|
|
// nsIEventListener interface
|
2007-03-22 10:30:00 -07:00
|
|
|
nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
|
|
|
|
|
2007-07-02 20:33:13 -07:00
|
|
|
#ifdef XP_WIN
|
2008-10-29 22:28:25 -07:00
|
|
|
void Paint(const RECT& aDirty, HDC aDC);
|
2007-07-02 20:33:13 -07:00
|
|
|
#elif defined(XP_MACOSX)
|
2009-08-26 17:29:47 -07:00
|
|
|
void Paint(const gfxRect& aDirtyRect);
|
2008-08-06 13:48:55 -07:00
|
|
|
#elif defined(MOZ_X11) || defined(MOZ_DFB)
|
2008-07-06 19:49:38 -07:00
|
|
|
void Paint(gfxContext* aContext,
|
|
|
|
const gfxRect& aFrameRect,
|
|
|
|
const gfxRect& aDirtyRect);
|
2008-03-10 17:10:55 -07:00
|
|
|
#elif defined(XP_OS2)
|
|
|
|
void Paint(const nsRect& aDirtyRect, HPS aHPS);
|
2007-07-02 20:33:13 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// nsITimerCallback interface
|
|
|
|
NS_DECL_NSITIMERCALLBACK
|
|
|
|
|
|
|
|
void CancelTimer();
|
|
|
|
void StartTimer(unsigned int aDelay);
|
|
|
|
|
|
|
|
// nsIScrollPositionListener interface
|
|
|
|
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
2009-07-21 17:45:13 -07:00
|
|
|
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
|
|
|
|
nsTArray<nsIWidget::Configuration>* aConfigurations) {}
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
|
|
|
|
|
|
|
//locals
|
|
|
|
|
|
|
|
nsresult Init(nsPresContext* aPresContext, nsObjectFrame* aFrame,
|
|
|
|
nsIContent* aContent);
|
|
|
|
|
|
|
|
nsPluginPort* GetPluginPort();
|
|
|
|
void ReleasePluginPort(nsPluginPort * pluginPort);
|
|
|
|
|
|
|
|
void SetPluginHost(nsIPluginHost* aHost);
|
|
|
|
|
|
|
|
#ifdef XP_MACOSX
|
2007-03-26 18:07:57 -07:00
|
|
|
NPDrawingModel GetDrawingModel();
|
2009-08-26 17:29:47 -07:00
|
|
|
NPEventModel GetEventModel();
|
|
|
|
void* FixUpPluginWindow(PRInt32 inPaintState);
|
2008-10-30 10:40:53 -07:00
|
|
|
// Set a flag that (if true) indicates the plugin port info has changed and
|
|
|
|
// SetWindow() needs to be called.
|
|
|
|
void SetPluginPortChanged(PRBool aState) { mPluginPortChanged = aState; }
|
|
|
|
// Return a pointer to the internal nsPluginPort structure that's used to
|
|
|
|
// store a copy of plugin port info and to detect when it's been changed.
|
|
|
|
nsPluginPort* GetPluginPortCopy() { return &mPluginPortCopy; }
|
|
|
|
// Set plugin port info in the plugin (in the 'window' member of the
|
|
|
|
// nsPluginWindow structure passed to the plugin by SetWindow()) and set a
|
|
|
|
// flag (mPluginPortChanged) to indicate whether or not this info has
|
|
|
|
// changed, and SetWindow() needs to be called again.
|
|
|
|
nsPluginPort* SetPluginPortAndDetectChange();
|
|
|
|
// Flag when we've set up a Thebes (and CoreGraphics) context in
|
|
|
|
// nsObjectFrame::PaintPlugin(). We need to know this in
|
|
|
|
// FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
|
|
|
|
// been called from nsObjectFrame::PaintPlugin() when we're using the
|
|
|
|
// CoreGraphics drawing model).
|
|
|
|
void BeginCGPaint();
|
|
|
|
void EndCGPaint();
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
void SetOwner(nsObjectFrame *aOwner)
|
|
|
|
{
|
|
|
|
mOwner = aOwner;
|
|
|
|
}
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
PRUint32 GetLastEventloopNestingLevel() const {
|
|
|
|
return mLastEventloopNestingLevel;
|
|
|
|
}
|
|
|
|
|
2009-02-02 17:23:48 -08:00
|
|
|
static PRUint32 GetEventloopNestingLevel();
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
void ConsiderNewEventloopNestingLevel() {
|
2009-02-02 17:23:48 -08:00
|
|
|
PRUint32 currentLevel = GetEventloopNestingLevel();
|
|
|
|
|
|
|
|
if (currentLevel < mLastEventloopNestingLevel) {
|
|
|
|
mLastEventloopNestingLevel = currentLevel;
|
2008-03-25 09:56:04 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-04-16 13:06:48 -07:00
|
|
|
const char* GetPluginName()
|
|
|
|
{
|
|
|
|
if (mInstance && mPluginHost) {
|
2008-07-07 17:23:04 -07:00
|
|
|
const char* name = NULL;
|
2009-06-30 13:49:04 -07:00
|
|
|
if (NS_SUCCEEDED(mPluginHost->GetPluginName(mInstance, &name)) && name)
|
2008-04-16 13:06:48 -07:00
|
|
|
return name;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2008-12-14 19:54:54 -08:00
|
|
|
PRBool SendNativeEvents()
|
|
|
|
{
|
|
|
|
#ifdef XP_WIN
|
|
|
|
return MatchPluginName("Shockwave Flash");
|
|
|
|
#else
|
|
|
|
return PR_FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool MatchPluginName(const char *aPluginName)
|
|
|
|
{
|
|
|
|
return strncmp(GetPluginName(), aPluginName, strlen(aPluginName)) == 0;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
private:
|
|
|
|
void FixUpURLS(const nsString &name, nsAString &value);
|
|
|
|
|
|
|
|
nsPluginNativeWindow *mPluginWindow;
|
|
|
|
nsCOMPtr<nsIPluginInstance> mInstance;
|
|
|
|
nsObjectFrame *mOwner;
|
|
|
|
nsCOMPtr<nsIContent> mContent;
|
|
|
|
nsCString mDocumentBase;
|
|
|
|
char *mTagText;
|
|
|
|
nsCOMPtr<nsIWidget> mWidget;
|
|
|
|
nsCOMPtr<nsITimer> mPluginTimer;
|
|
|
|
nsCOMPtr<nsIPluginHost> mPluginHost;
|
2008-03-25 09:56:04 -07:00
|
|
|
|
2008-10-30 10:40:53 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
nsPluginPort mPluginPortCopy;
|
|
|
|
PRInt32 mInCGPaintLevel;
|
|
|
|
#endif
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
// Initially, the event loop nesting level we were created on, it's updated
|
|
|
|
// if we detect the appshell is on a lower level as long as we're not stopped.
|
|
|
|
// We delay DoStopPlugin() until the appshell reaches this level or lower.
|
|
|
|
PRUint32 mLastEventloopNestingLevel;
|
2007-03-22 10:30:00 -07:00
|
|
|
PRPackedBool mContentFocused;
|
|
|
|
PRPackedBool mWidgetVisible; // used on Mac to store our widget's visible state
|
2008-10-30 10:40:53 -07:00
|
|
|
PRPackedBool mPluginPortChanged;
|
2007-08-13 13:47:04 -07:00
|
|
|
|
|
|
|
// If true, destroy the widget on destruction. Used when plugin stop
|
|
|
|
// is being delayed to a safer point in time.
|
|
|
|
PRPackedBool mDestroyWidget;
|
2008-12-03 01:30:40 -08:00
|
|
|
PRPackedBool mTimerCanceled;
|
2007-03-22 10:30:00 -07:00
|
|
|
PRUint16 mNumCachedAttrs;
|
|
|
|
PRUint16 mNumCachedParams;
|
|
|
|
char **mCachedAttrParamNames;
|
|
|
|
char **mCachedAttrParamValues;
|
2008-02-28 18:06:00 -08:00
|
|
|
|
2009-02-25 07:25:12 -08:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
nsIntPoint mLastPoint;
|
|
|
|
#endif
|
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
// pointer to wrapper for nsIDOMContextMenuListener
|
|
|
|
nsRefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent);
|
|
|
|
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent);
|
|
|
|
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
|
|
|
|
|
|
|
|
nsresult EnsureCachedAttrParamArrays();
|
2007-07-02 20:33:13 -07:00
|
|
|
|
2009-02-25 07:25:12 -08:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
nsEventStatus ProcessEventX11Composited(const nsGUIEvent & anEvent);
|
|
|
|
#endif
|
|
|
|
|
2008-08-09 06:43:08 -07:00
|
|
|
#if defined(MOZ_WIDGET_GTK2)
|
2008-08-06 13:48:55 -07:00
|
|
|
class Renderer : public gfxGdkNativeRenderer {
|
2007-07-02 20:33:13 -07:00
|
|
|
public:
|
|
|
|
Renderer(nsPluginWindow* aWindow, nsIPluginInstance* aInstance,
|
2008-07-06 19:49:38 -07:00
|
|
|
const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
|
|
|
|
: mWindow(aWindow), mInstance(aInstance),
|
|
|
|
mPluginSize(aPluginSize), mDirtyRect(aDirtyRect)
|
2007-07-02 20:33:13 -07:00
|
|
|
{}
|
2008-08-06 13:48:55 -07:00
|
|
|
virtual nsresult NativeDraw(GdkDrawable * drawable, short offsetX,
|
|
|
|
short offsetY, GdkRectangle * clipRects, PRUint32 numClipRects);
|
2007-07-02 20:33:13 -07:00
|
|
|
private:
|
|
|
|
nsPluginWindow* mWindow;
|
|
|
|
nsIPluginInstance* mInstance;
|
2008-07-06 19:49:38 -07:00
|
|
|
const nsIntSize& mPluginSize;
|
2007-07-02 20:33:13 -07:00
|
|
|
const nsIntRect& mDirtyRect;
|
|
|
|
};
|
2008-08-09 06:43:08 -07:00
|
|
|
#elif defined(MOZ_WIDGET_QT)
|
|
|
|
class Renderer : public gfxQtNativeRenderer {
|
|
|
|
public:
|
|
|
|
Renderer(nsPluginWindow* aWindow, nsIPluginInstance* aInstance,
|
|
|
|
const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
|
|
|
|
: mWindow(aWindow), mInstance(aInstance),
|
|
|
|
mPluginSize(aPluginSize), mDirtyRect(aDirtyRect)
|
|
|
|
{}
|
|
|
|
virtual nsresult NativeDraw(QWidget * drawable, short offsetX,
|
|
|
|
short offsetY, QRect * clipRects, PRUint32 numClipRects);
|
|
|
|
private:
|
|
|
|
nsPluginWindow* mWindow;
|
|
|
|
nsIPluginInstance* mInstance;
|
|
|
|
const nsIntSize& mPluginSize;
|
|
|
|
const nsIntRect& mDirtyRect;
|
|
|
|
};
|
2007-07-02 20:33:13 -07:00
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
2009-07-21 17:45:02 -07:00
|
|
|
// Mac specific code to fix up port position and clip
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
|
2009-07-21 17:45:02 -07:00
|
|
|
enum { ePluginPaintEnable, ePluginPaintDisable };
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#endif // XP_MACOSX
|
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
nsObjectFrame::nsObjectFrame(nsStyleContext* aContext)
|
|
|
|
: nsObjectFrameSuper(aContext)
|
|
|
|
{
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("Created new nsObjectFrame %p\n", this));
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsObjectFrame::~nsObjectFrame()
|
|
|
|
{
|
2008-02-28 18:06:00 -08:00
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("nsObjectFrame %p deleted\n", this));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-01-12 11:20:59 -08:00
|
|
|
NS_QUERYFRAME_HEAD(nsObjectFrame)
|
|
|
|
NS_QUERYFRAME_ENTRY(nsIObjectFrame)
|
|
|
|
NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
NS_IMETHODIMP nsObjectFrame::GetAccessible(nsIAccessible** aAccessible)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAccessibilityService> accService = do_GetService("@mozilla.org/accessibilityService;1");
|
|
|
|
|
|
|
|
if (accService) {
|
|
|
|
return accService->CreateHTMLObjectFrameAccessible(this, aAccessible);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef XP_WIN
|
|
|
|
NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
|
|
|
|
{
|
|
|
|
*aPort = (HWND) mInstanceOwner->GetPluginPort();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectFrame::Init(nsIContent* aContent,
|
|
|
|
nsIFrame* aParent,
|
|
|
|
nsIFrame* aPrevInFlow)
|
|
|
|
{
|
2008-10-04 13:00:09 -07:00
|
|
|
NS_PRECONDITION(aContent, "How did that happen?");
|
|
|
|
mPreventInstantiation =
|
|
|
|
(aContent->GetCurrentDoc()->GetDisplayDocument() != nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("Initializing nsObjectFrame %p for content %p\n", this, aContent));
|
|
|
|
|
2007-08-06 17:32:14 -07:00
|
|
|
return nsObjectFrameSuper::Init(aContent, aParent, aPrevInFlow);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::Destroy()
|
|
|
|
{
|
2008-10-04 13:00:09 -07:00
|
|
|
NS_ASSERTION(!mPreventInstantiation ||
|
2009-06-29 11:53:52 -07:00
|
|
|
(mContent && mContent->GetCurrentDoc()->GetDisplayDocument()),
|
2008-10-04 13:00:09 -07:00
|
|
|
"about to crash due to bug 136927");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-07-21 17:45:00 -07:00
|
|
|
PresContext()->RootPresContext()->UnregisterPluginForGeometryUpdates(this);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// we need to finish with the plugin before native window is destroyed
|
|
|
|
// doing this in the destructor is too late.
|
2007-08-13 13:47:04 -07:00
|
|
|
StopPluginInternal(PR_TRUE);
|
2009-07-21 17:45:00 -07:00
|
|
|
|
|
|
|
// StopPluginInternal might have disowned the widget; if it has,
|
|
|
|
// mWidget will be null.
|
|
|
|
if (mWidget) {
|
|
|
|
GetView()->DetachWidgetEventHandler(mWidget);
|
|
|
|
mWidget->Destroy();
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsObjectFrameSuper::Destroy();
|
|
|
|
}
|
|
|
|
|
2008-10-13 15:03:28 -07:00
|
|
|
/* virtual */ void
|
2008-10-26 03:11:34 -07:00
|
|
|
nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
2007-10-18 20:41:07 -07:00
|
|
|
{
|
|
|
|
if (HasView()) {
|
|
|
|
nsIView* view = GetView();
|
|
|
|
nsIViewManager* vm = view->GetViewManager();
|
|
|
|
if (vm) {
|
|
|
|
nsViewVisibility visibility =
|
|
|
|
IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow;
|
|
|
|
vm->SetViewVisibility(view, visibility);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-26 03:11:34 -07:00
|
|
|
nsObjectFrameSuper::DidSetStyleContext(aOldStyleContext);
|
2007-10-18 20:41:07 -07:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIAtom*
|
|
|
|
nsObjectFrame::GetType() const
|
|
|
|
{
|
|
|
|
return nsGkAtoms::objectFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectFrame::GetFrameName(nsAString& aResult) const
|
|
|
|
{
|
|
|
|
return MakeFrameName(NS_LITERAL_STRING("ObjectFrame"), aResult);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsObjectFrame::CreateWidgetForView(nsIView* aView)
|
|
|
|
{
|
|
|
|
// Bug 179822: Create widget and allow non-unicode SubClass
|
|
|
|
nsWidgetInitData initData;
|
|
|
|
initData.mUnicode = PR_FALSE;
|
2009-07-21 17:45:00 -07:00
|
|
|
initData.clipChildren = PR_TRUE;
|
|
|
|
initData.clipSiblings = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
return aView->CreateWidget(kWidgetCID, &initData);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsObjectFrame::CreateWidget(nscoord aWidth,
|
|
|
|
nscoord aHeight,
|
|
|
|
PRBool aViewOnly)
|
|
|
|
{
|
|
|
|
nsIView* view = GetView();
|
|
|
|
NS_ASSERTION(view, "Object frames must have views");
|
|
|
|
if (!view) {
|
|
|
|
return NS_OK; //XXX why OK? MMP
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIViewManager* viewMan = view->GetViewManager();
|
|
|
|
// mark the view as hidden since we don't know the (x,y) until Paint
|
|
|
|
// XXX is the above comment correct?
|
|
|
|
viewMan->SetViewVisibility(view, nsViewVisibility_kHide);
|
|
|
|
|
2009-07-21 17:45:00 -07:00
|
|
|
PRBool usewidgets;
|
|
|
|
nsCOMPtr<nsIDeviceContext> dx;
|
|
|
|
viewMan->GetDeviceContext(*getter_AddRefs(dx));
|
|
|
|
dx->SupportsNativeWidgets(usewidgets);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
//this is ugly. it was ripped off from didreflow(). MMP
|
|
|
|
// Position and size view relative to its parent, not relative to our
|
|
|
|
// parent frame (our parent frame may not have a view).
|
|
|
|
|
|
|
|
nsIView* parentWithView;
|
|
|
|
nsPoint origin;
|
|
|
|
nsRect r(0, 0, mRect.width, mRect.height);
|
|
|
|
|
|
|
|
GetOffsetFromView(origin, &parentWithView);
|
|
|
|
viewMan->ResizeView(view, r);
|
|
|
|
viewMan->MoveViewTo(view, origin.x, origin.y);
|
|
|
|
|
2009-07-21 17:45:00 -07:00
|
|
|
if (!aViewOnly && !mWidget && usewidgets) {
|
|
|
|
nsresult rv;
|
|
|
|
mWidget = do_CreateInstance(kWidgetCID, &rv);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsRootPresContext* rpc = PresContext()->RootPresContext();
|
|
|
|
// XXX this breaks plugins in popups ... do we care?
|
|
|
|
nsIWidget* parentWidget =
|
|
|
|
rpc->PresShell()->FrameManager()->GetRootFrame()->GetWindow();
|
|
|
|
|
|
|
|
nsWidgetInitData initData;
|
|
|
|
initData.mUnicode = PR_FALSE;
|
|
|
|
initData.clipChildren = PR_TRUE;
|
|
|
|
initData.clipSiblings = PR_TRUE;
|
|
|
|
// We want mWidget to be able to deliver events to us, especially on
|
|
|
|
// Mac where events to the plugin are routed through Gecko. So we
|
|
|
|
// allow the view to attach its event handler to mWidget even though
|
|
|
|
// mWidget isn't the view's designated widget.
|
|
|
|
EVENT_CALLBACK eventHandler = view->AttachWidgetEventHandler(mWidget);
|
|
|
|
mWidget->Create(parentWidget, nsIntRect(0,0,0,0),
|
|
|
|
eventHandler, dx, nsnull, nsnull, &initData);
|
|
|
|
|
|
|
|
mWidget->EnableDragDrop(PR_TRUE);
|
|
|
|
|
|
|
|
rpc->RegisterPluginForGeometryUpdates(this);
|
|
|
|
rpc->UpdatePluginGeometry(this);
|
|
|
|
|
|
|
|
mWidget->Show(PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-07-21 17:45:00 -07:00
|
|
|
if (mWidget) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// Here we set the background color for this widget because some plugins will use
|
|
|
|
// the child window background color when painting. If it's not set, it may default to gray
|
|
|
|
// Sometimes, a frame doesn't have a background color or is transparent. In this
|
|
|
|
// case, walk up the frame tree until we do find a frame with a background color
|
|
|
|
for (nsIFrame* frame = this; frame; frame = frame->GetParent()) {
|
|
|
|
const nsStyleBackground* background = frame->GetStyleBackground();
|
|
|
|
if (!background->IsTransparent()) { // make sure we got an actual color
|
2009-07-21 17:45:00 -07:00
|
|
|
mWidget->SetBackgroundColor(background->mBackgroundColor);
|
2007-03-22 10:30:00 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-18 20:41:07 -07:00
|
|
|
if (!IsHidden()) {
|
|
|
|
viewMan->SetViewVisibility(view, nsViewVisibility_kShow);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EMBED_DEF_WIDTH 240
|
|
|
|
#define EMBED_DEF_HEIGHT 200
|
|
|
|
|
|
|
|
/* virtual */ nscoord
|
|
|
|
nsObjectFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
|
|
|
{
|
|
|
|
nscoord result = 0;
|
|
|
|
|
|
|
|
if (!IsHidden(PR_FALSE)) {
|
|
|
|
nsIAtom *atom = mContent->Tag();
|
|
|
|
if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
|
|
|
|
result = nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DISPLAY_MIN_WIDTH(this, result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nscoord
|
|
|
|
nsObjectFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
|
|
|
{
|
|
|
|
return nsObjectFrame::GetMinWidth(aRenderingContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsHTMLReflowMetrics& aMetrics)
|
|
|
|
{
|
|
|
|
// By default, we have no area
|
|
|
|
aMetrics.width = 0;
|
|
|
|
aMetrics.height = 0;
|
|
|
|
|
|
|
|
if (IsHidden(PR_FALSE)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
aMetrics.width = aReflowState.ComputedWidth();
|
2007-08-02 11:08:05 -07:00
|
|
|
aMetrics.height = aReflowState.ComputedHeight();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// for EMBED and APPLET, default to 240x200 for compatibility
|
|
|
|
nsIAtom *atom = mContent->Tag();
|
|
|
|
if (atom == nsGkAtoms::applet || atom == nsGkAtoms::embed) {
|
|
|
|
if (aMetrics.width == NS_UNCONSTRAINEDSIZE) {
|
|
|
|
aMetrics.width = PR_MIN(PR_MAX(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_WIDTH),
|
|
|
|
aReflowState.mComputedMinWidth),
|
|
|
|
aReflowState.mComputedMaxWidth);
|
|
|
|
}
|
|
|
|
if (aMetrics.height == NS_UNCONSTRAINEDSIZE) {
|
|
|
|
aMetrics.height = PR_MIN(PR_MAX(nsPresContext::CSSPixelsToAppUnits(EMBED_DEF_HEIGHT),
|
|
|
|
aReflowState.mComputedMinHeight),
|
|
|
|
aReflowState.mComputedMaxHeight);
|
|
|
|
}
|
|
|
|
|
2007-04-30 16:52:44 -07:00
|
|
|
#if defined (MOZ_WIDGET_GTK2)
|
2007-03-22 10:30:00 -07:00
|
|
|
// We need to make sure that the size of the object frame does not
|
|
|
|
// exceed the maximum size of X coordinates. See bug #225357 for
|
|
|
|
// more information. In theory Gtk2 can handle large coordinates,
|
|
|
|
// but underlying plugins can't.
|
|
|
|
aMetrics.height = PR_MIN(aPresContext->DevPixelsToAppUnits(PR_INT16_MAX), aMetrics.height);
|
|
|
|
aMetrics.width = PR_MIN(aPresContext->DevPixelsToAppUnits(PR_INT16_MAX), aMetrics.width);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// At this point, the width has an unconstrained value only if we have
|
|
|
|
// nothing to go on (no width set, no information from the plugin, nothing).
|
|
|
|
// Make up a number.
|
|
|
|
if (aMetrics.width == NS_UNCONSTRAINEDSIZE) {
|
|
|
|
aMetrics.width =
|
|
|
|
(aReflowState.mComputedMinWidth != NS_UNCONSTRAINEDSIZE) ?
|
|
|
|
aReflowState.mComputedMinWidth : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// At this point, the height has an unconstrained value only in two cases:
|
|
|
|
// a) We are in standards mode with percent heights and parent is auto-height
|
|
|
|
// b) We have no height information at all.
|
|
|
|
// In either case, we have to make up a number.
|
|
|
|
if (aMetrics.height == NS_UNCONSTRAINEDSIZE) {
|
|
|
|
aMetrics.height =
|
|
|
|
(aReflowState.mComputedMinHeight != NS_UNCONSTRAINEDSIZE) ?
|
|
|
|
aReflowState.mComputedMinHeight : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXXbz don't add in the border and padding, because we screw up our
|
|
|
|
// plugin's size and positioning if we do... Eventually we _do_ want to
|
|
|
|
// paint borders, though! At that point, we will need to adjust the desired
|
|
|
|
// size either here or in Reflow.... Further, we will need to fix Paint() to
|
|
|
|
// call the superclass in all cases.
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectFrame::Reflow(nsPresContext* aPresContext,
|
|
|
|
nsHTMLReflowMetrics& aMetrics,
|
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nsReflowStatus& aStatus)
|
|
|
|
{
|
|
|
|
DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
|
|
|
|
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
|
|
|
|
|
|
|
// Get our desired size
|
|
|
|
GetDesiredSize(aPresContext, aReflowState, aMetrics);
|
2009-02-15 10:14:32 -08:00
|
|
|
aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
|
2009-01-29 23:05:46 -08:00
|
|
|
FinishAndStoreOverflow(&aMetrics);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// delay plugin instantiation until all children have
|
|
|
|
// arrived. Otherwise there may be PARAMs or other stuff that the
|
|
|
|
// plugin needs to see that haven't arrived yet.
|
|
|
|
if (!GetContent()->IsDoneAddingChildren()) {
|
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we are printing or print previewing, bail for now
|
|
|
|
if (aPresContext->Medium() == nsGkAtoms::print) {
|
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
FixupWindow(nsSize(aMetrics.width, aMetrics.height));
|
|
|
|
|
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
|
|
|
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsObjectFrame::InstantiatePlugin(nsIPluginHost* aPluginHost,
|
|
|
|
const char* aMimeType,
|
|
|
|
nsIURI* aURI)
|
|
|
|
{
|
2008-05-06 13:49:30 -07:00
|
|
|
NS_ASSERTION(mPreventInstantiation,
|
|
|
|
"Instantiation should be prevented here!");
|
|
|
|
|
2007-03-22 16:04:51 -07:00
|
|
|
// If you add early return(s), be sure to balance this call to
|
|
|
|
// appShell->SuspendNative() with additional call(s) to
|
|
|
|
// appShell->ReturnNative().
|
|
|
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
|
|
|
if (appShell) {
|
|
|
|
appShell->SuspendNative();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_ASSERTION(mContent, "We should have a content node.");
|
|
|
|
|
|
|
|
nsIDocument* doc = mContent->GetOwnerDoc();
|
|
|
|
nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc));
|
2008-10-07 11:53:23 -07:00
|
|
|
PRBool fullPageMode = PR_FALSE;
|
|
|
|
if (pDoc) {
|
|
|
|
pDoc->GetWillHandleInstantiation(&fullPageMode);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsresult rv;
|
2008-10-07 11:53:23 -07:00
|
|
|
if (fullPageMode) { /* full-page mode */
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIStreamListener> stream;
|
|
|
|
rv = aPluginHost->InstantiateFullPagePlugin(aMimeType, aURI,
|
|
|
|
/* resulting stream listener */ *getter_AddRefs(stream),
|
|
|
|
mInstanceOwner);
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
pDoc->SetStreamListener(stream);
|
|
|
|
} else { /* embedded mode */
|
|
|
|
rv = aPluginHost->InstantiateEmbeddedPlugin(aMimeType, aURI,
|
|
|
|
mInstanceOwner);
|
|
|
|
}
|
|
|
|
|
2008-06-27 12:37:21 -07:00
|
|
|
// Note that |this| may very well be destroyed already!
|
|
|
|
|
2007-03-22 16:04:51 -07:00
|
|
|
if (appShell) {
|
|
|
|
appShell->ResumeNative();
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::FixupWindow(const nsSize& aSize)
|
|
|
|
{
|
2007-03-30 14:11:41 -07:00
|
|
|
nsPresContext* presContext = PresContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (!mInstanceOwner)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsPluginWindow *window;
|
|
|
|
mInstanceOwner->GetWindow(window);
|
|
|
|
|
|
|
|
NS_ENSURE_TRUE(window, /**/);
|
|
|
|
|
2007-08-06 17:32:14 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
mInstanceOwner->FixUpPluginWindow(ePluginPaintDisable);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PRBool windowless = (window->type == nsPluginWindowType_Drawable);
|
|
|
|
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntPoint origin = GetWindowOriginInPixels(windowless);
|
2007-08-06 17:32:14 -07:00
|
|
|
|
|
|
|
window->x = origin.x;
|
|
|
|
window->y = origin.y;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
window->width = presContext->AppUnitsToDevPixels(aSize.width);
|
|
|
|
window->height = presContext->AppUnitsToDevPixels(aSize.height);
|
|
|
|
|
|
|
|
// on the Mac we need to set the clipRect to { 0, 0, 0, 0 } for now. This will keep
|
|
|
|
// us from drawing on screen until the widget is properly positioned, which will not
|
|
|
|
// happen until we have finished the reflow process.
|
|
|
|
window->clipRect.top = 0;
|
|
|
|
window->clipRect.left = 0;
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
window->clipRect.bottom = 0;
|
|
|
|
window->clipRect.right = 0;
|
|
|
|
#else
|
|
|
|
window->clipRect.bottom = presContext->AppUnitsToDevPixels(aSize.height);
|
|
|
|
window->clipRect.right = presContext->AppUnitsToDevPixels(aSize.width);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2007-08-20 10:40:08 -07:00
|
|
|
void
|
|
|
|
nsObjectFrame::CallSetWindow()
|
|
|
|
{
|
|
|
|
nsPluginWindow *win = nsnull;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIPluginInstance> pi;
|
|
|
|
if (!mInstanceOwner ||
|
|
|
|
NS_FAILED(rv = mInstanceOwner->GetInstance(*getter_AddRefs(pi))) ||
|
|
|
|
!pi ||
|
|
|
|
NS_FAILED(rv = mInstanceOwner->GetWindow(win)) ||
|
|
|
|
!win)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
|
|
|
|
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
mInstanceOwner->FixUpPluginWindow(ePluginPaintDisable);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (IsHidden())
|
|
|
|
return;
|
|
|
|
|
|
|
|
PRBool windowless = (window->type == nsPluginWindowType_Drawable);
|
|
|
|
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntPoint origin = GetWindowOriginInPixels(windowless);
|
2007-08-20 10:40:08 -07:00
|
|
|
|
|
|
|
window->x = origin.x;
|
|
|
|
window->y = origin.y;
|
|
|
|
|
|
|
|
// refresh the plugin port as well
|
2008-07-07 19:15:40 -07:00
|
|
|
window->window = mInstanceOwner->GetPluginPort();
|
2007-08-20 10:40:08 -07:00
|
|
|
|
|
|
|
// this will call pi->SetWindow and take care of window subclassing
|
|
|
|
// if needed, see bug 132759.
|
|
|
|
window->CallSetWindow(pi);
|
|
|
|
|
|
|
|
mInstanceOwner->ReleasePluginPort((nsPluginPort *)window->window);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
PRBool
|
|
|
|
nsObjectFrame::IsFocusable(PRInt32 *aTabIndex, PRBool aWithMouse)
|
|
|
|
{
|
|
|
|
if (aTabIndex)
|
|
|
|
*aTabIndex = -1;
|
|
|
|
return nsObjectFrameSuper::IsFocusable(aTabIndex, aWithMouse);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsObjectFrame::IsHidden(PRBool aCheckVisibilityStyle) const
|
|
|
|
{
|
|
|
|
if (aCheckVisibilityStyle) {
|
|
|
|
if (!GetStyleVisibility()->IsVisibleOrCollapsed())
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// only <embed> tags support the HIDDEN attribute
|
|
|
|
if (mContent->Tag() == nsGkAtoms::embed) {
|
|
|
|
// Yes, these are really the kooky ways that you could tell 4.x
|
|
|
|
// not to hide the <embed> once you'd put the 'hidden' attribute
|
|
|
|
// on the tag...
|
|
|
|
|
|
|
|
// HIDDEN w/ no attributes gets translated as we are hidden for
|
|
|
|
// compatibility w/ 4.x and IE so we don't create a non-painting
|
|
|
|
// widget in layout. See bug 188959.
|
|
|
|
nsAutoString hidden;
|
|
|
|
if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::hidden, hidden) &&
|
|
|
|
(hidden.IsEmpty() ||
|
2008-09-15 08:40:25 -07:00
|
|
|
(!hidden.LowerCaseEqualsLiteral("false") &&
|
|
|
|
!hidden.LowerCaseEqualsLiteral("no") &&
|
|
|
|
!hidden.LowerCaseEqualsLiteral("off")))) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntPoint nsObjectFrame::GetWindowOriginInPixels(PRBool aWindowless)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsIView * parentWithView;
|
|
|
|
nsPoint origin(0,0);
|
|
|
|
|
|
|
|
GetOffsetFromView(origin, &parentWithView);
|
|
|
|
|
|
|
|
// if it's windowless, let's make sure we have our origin set right
|
|
|
|
// it may need to be corrected, like after scrolling
|
|
|
|
if (aWindowless && parentWithView) {
|
2009-07-29 19:56:52 -07:00
|
|
|
nsPoint offsetToWidget;
|
|
|
|
parentWithView->GetNearestWidget(&offsetToWidget);
|
|
|
|
origin += offsetToWidget;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-01-14 19:27:09 -08:00
|
|
|
return nsIntPoint(PresContext()->AppUnitsToDevPixels(origin.x),
|
|
|
|
PresContext()->AppUnitsToDevPixels(origin.y));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectFrame::DidReflow(nsPresContext* aPresContext,
|
|
|
|
const nsHTMLReflowState* aReflowState,
|
|
|
|
nsDidReflowStatus aStatus)
|
|
|
|
{
|
2007-08-06 17:32:14 -07:00
|
|
|
// Do this check before calling the superclass, as that clears
|
|
|
|
// NS_FRAME_FIRST_REFLOW
|
|
|
|
if (aStatus == NS_FRAME_REFLOW_FINISHED &&
|
|
|
|
(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
|
|
|
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(mContent));
|
|
|
|
NS_ASSERTION(objContent, "Why not an object loading content?");
|
|
|
|
objContent->HasNewFrame(this);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv = nsObjectFrameSuper::DidReflow(aPresContext, aReflowState, aStatus);
|
|
|
|
|
|
|
|
// The view is created hidden; once we have reflowed it and it has been
|
|
|
|
// positioned then we show it.
|
|
|
|
if (aStatus != NS_FRAME_REFLOW_FINISHED)
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (HasView()) {
|
|
|
|
nsIView* view = GetView();
|
|
|
|
nsIViewManager* vm = view->GetViewManager();
|
|
|
|
if (vm)
|
2007-08-20 10:40:08 -07:00
|
|
|
vm->SetViewVisibility(view, IsHidden() ? nsViewVisibility_kHide : nsViewVisibility_kShow);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-08-20 10:40:08 -07:00
|
|
|
// WMP10 needs an additional SetWindow call here (bug 391261)
|
|
|
|
CallSetWindow();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2008-07-06 19:49:38 -07:00
|
|
|
/* static */ void
|
|
|
|
nsObjectFrame::PaintPrintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
|
|
|
const nsRect& aDirtyRect, nsPoint aPt)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-07-06 19:49:38 -07:00
|
|
|
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIRenderingContext::AutoPushTranslation translate(aCtx, aPt.x, aPt.y);
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-07-21 17:45:00 -07:00
|
|
|
nsRect
|
|
|
|
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-07-21 17:45:00 -07:00
|
|
|
return mFrame->GetContentRect() +
|
|
|
|
aBuilder->ToReferenceFrame(mFrame->GetParent());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsIRenderingContext* aCtx,
|
|
|
|
const nsRect& aDirtyRect)
|
|
|
|
{
|
|
|
|
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
|
|
|
f->PaintPlugin(*aCtx, aDirtyRect, GetBounds(aBuilder).TopLeft());
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsDisplayPlugin::OptimizeVisibility(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsRegion* aVisibleRegion)
|
|
|
|
{
|
|
|
|
mVisibleRegion.And(*aVisibleRegion, GetBounds(aBuilder));
|
|
|
|
return nsDisplayItem::OptimizeVisibility(aBuilder, aVisibleRegion);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsDisplayPlugin::IsOpaque(nsDisplayListBuilder* aBuilder)
|
|
|
|
{
|
|
|
|
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
|
|
|
return f->IsOpaque();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDisplayPlugin::GetWidgetConfiguration(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsTArray<nsIWidget::Configuration>* aConfigurations)
|
|
|
|
{
|
|
|
|
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
|
|
|
f->ComputeWidgetGeometry(mVisibleRegion, aBuilder->ToReferenceFrame(mFrame),
|
|
|
|
aConfigurations);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::ComputeWidgetGeometry(const nsRegion& aRegion,
|
|
|
|
const nsPoint& aPluginOrigin,
|
|
|
|
nsTArray<nsIWidget::Configuration>* aConfigurations)
|
|
|
|
{
|
|
|
|
if (!mWidget)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsIWidget::Configuration* configuration =
|
|
|
|
aConfigurations->AppendElement();
|
|
|
|
if (!configuration)
|
|
|
|
return;
|
|
|
|
configuration->mChild = mWidget;
|
|
|
|
|
|
|
|
nsPresContext* presContext = PresContext();
|
|
|
|
PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
|
|
|
nsIFrame* rootFrame =
|
|
|
|
presContext->RootPresContext()->PresShell()->FrameManager()->GetRootFrame();
|
|
|
|
nsRect bounds = GetContentRect() + GetParent()->GetOffsetTo(rootFrame);
|
|
|
|
configuration->mBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
|
|
|
|
|
|
|
|
nsRegionRectIterator iter(aRegion);
|
|
|
|
nsIntPoint pluginOrigin = aPluginOrigin.ToNearestPixels(appUnitsPerDevPixel);
|
|
|
|
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
|
|
|
|
// Snap *r to pixels while it's relative to the painted widget, to
|
|
|
|
// improve consistency with rectangle and image drawing
|
|
|
|
nsIntRect pixRect =
|
|
|
|
r->ToNearestPixels(appUnitsPerDevPixel) - pluginOrigin;
|
|
|
|
if (!pixRect.IsEmpty()) {
|
|
|
|
configuration->mClipRegion.AppendElement(pixRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-21 17:45:02 -07:00
|
|
|
void
|
|
|
|
nsObjectFrame::DidSetWidgetGeometry()
|
|
|
|
{
|
|
|
|
#if defined(XP_MACOSX)
|
|
|
|
if (mInstanceOwner) {
|
|
|
|
mInstanceOwner->FixUpPluginWindow(ePluginPaintEnable);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-07-21 17:45:00 -07:00
|
|
|
PRBool
|
|
|
|
nsObjectFrame::IsOpaque() const
|
|
|
|
{
|
|
|
|
#if defined(XP_MACOSX)
|
|
|
|
return PR_FALSE;
|
|
|
|
#else
|
|
|
|
if (mInstanceOwner) {
|
|
|
|
nsPluginWindow * window;
|
|
|
|
mInstanceOwner->GetWindow(window);
|
|
|
|
if (window->type == nsPluginWindowType_Drawable) {
|
|
|
|
// XXX we possibly should call nsPluginInstanceVariable_TransparentBool
|
|
|
|
// here to optimize for windowless but opaque plugins
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_TRUE;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsRect& aDirtyRect,
|
|
|
|
const nsDisplayListSet& aLists)
|
|
|
|
{
|
|
|
|
// XXX why are we painting collapsed object frames?
|
|
|
|
if (!IsVisibleOrCollapsedForPainting(aBuilder))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2007-03-30 14:11:41 -07:00
|
|
|
nsPresContext::nsPresContextType type = PresContext()->Type();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// If we are painting in Print Preview do nothing....
|
|
|
|
if (type == nsPresContext::eContext_PrintPreview)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
DO_GLOBAL_REFLOW_COUNT_DSP("nsObjectFrame");
|
2009-07-21 17:45:14 -07:00
|
|
|
|
|
|
|
#ifndef XP_MACOSX
|
|
|
|
if (mWidget && aBuilder->IsInTransform()) {
|
|
|
|
// Windowed plugins should not be rendered inside a transform.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// determine if we are printing
|
|
|
|
if (type == nsPresContext::eContext_Print)
|
|
|
|
return aLists.Content()->AppendNewToTop(new (aBuilder)
|
|
|
|
nsDisplayGeneric(this, PaintPrintPlugin, "PrintPlugin"));
|
2009-07-21 17:45:14 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return aLists.Content()->AppendNewToTop(new (aBuilder)
|
2009-07-21 17:45:00 -07:00
|
|
|
nsDisplayPlugin(this));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::PrintPlugin(nsIRenderingContext& aRenderingContext,
|
|
|
|
const nsRect& aDirtyRect)
|
|
|
|
{
|
|
|
|
// if we are printing, we need to get the correct nsIPluginInstance
|
|
|
|
// for THIS content node in order to call ->Print() on the right plugin
|
|
|
|
|
|
|
|
// first, we need to get the document
|
|
|
|
nsIDocument* doc = mContent->GetCurrentDoc();
|
|
|
|
if (!doc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// now we need to get the shell for the screen
|
|
|
|
// XXX assuming that the shell at zero will always be the screen one
|
2007-05-01 15:24:20 -07:00
|
|
|
nsIPresShell *shell = doc->GetPrimaryShell();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!shell)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// then the shell can give us the screen frame for this content node
|
|
|
|
nsIFrame* frame = shell->GetPrimaryFrameFor(mContent);
|
|
|
|
if (!frame)
|
|
|
|
return;
|
|
|
|
|
2007-03-30 14:11:41 -07:00
|
|
|
nsPresContext* presContext = PresContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
// make sure this is REALLY an nsIObjectFrame
|
|
|
|
// we may need to go through the children to get it
|
2009-01-12 11:20:59 -08:00
|
|
|
nsIObjectFrame* objectFrame = do_QueryFrame(frame);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!objectFrame)
|
|
|
|
objectFrame = GetNextObjectFrame(presContext,frame);
|
|
|
|
if (!objectFrame)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// finally we can get our plugin instance
|
|
|
|
nsCOMPtr<nsIPluginInstance> pi;
|
|
|
|
if (NS_FAILED(objectFrame->GetPluginInstance(*getter_AddRefs(pi))) || !pi)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// now we need to setup the correct location for printing
|
|
|
|
nsPluginWindow window;
|
|
|
|
window.window = nsnull;
|
|
|
|
|
|
|
|
// prepare embedded mode printing struct
|
|
|
|
nsPluginPrint npprint;
|
|
|
|
npprint.mode = nsPluginMode_Embedded;
|
|
|
|
|
|
|
|
// we need to find out if we are windowless or not
|
|
|
|
PRBool windowless = PR_FALSE;
|
|
|
|
pi->GetValue(nsPluginInstanceVariable_WindowlessBool, (void *)&windowless);
|
|
|
|
window.type = windowless ? nsPluginWindowType_Drawable : nsPluginWindowType_Window;
|
|
|
|
|
|
|
|
window.clipRect.bottom = 0; window.clipRect.top = 0;
|
|
|
|
window.clipRect.left = 0; window.clipRect.right = 0;
|
|
|
|
|
2009-07-20 15:10:36 -07:00
|
|
|
// platform specific printing code
|
|
|
|
#if defined(XP_MACOSX)
|
|
|
|
window.x = 0;
|
|
|
|
window.y = 0;
|
|
|
|
window.width = presContext->AppUnitsToDevPixels(mRect.width);
|
|
|
|
window.height = presContext->AppUnitsToDevPixels(mRect.height);
|
|
|
|
|
|
|
|
gfxContext *ctx = aRenderingContext.ThebesContext();
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
|
|
|
gfxContextAutoSaveRestore save(ctx);
|
|
|
|
|
|
|
|
ctx->NewPath();
|
|
|
|
|
|
|
|
gfxRect rect(window.x, window.y, window.width, window.height);
|
|
|
|
|
|
|
|
ctx->Rectangle(rect);
|
|
|
|
ctx->Clip();
|
|
|
|
|
|
|
|
gfxQuartzNativeDrawing nativeDraw(ctx, rect);
|
|
|
|
CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
|
|
|
|
if (!cgContext) {
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.clipRect.right = window.width;
|
|
|
|
window.clipRect.bottom = window.height;
|
|
|
|
window.type = nsPluginWindowType_Drawable;
|
|
|
|
|
|
|
|
Rect gwBounds;
|
|
|
|
::SetRect(&gwBounds, 0, 0, window.width, window.height);
|
|
|
|
|
|
|
|
nsTArray<char> buffer(window.width * window.height * 4);
|
|
|
|
CGColorSpaceRef cspace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
|
|
|
if (!cspace) {
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
CGContextRef cgBuffer =
|
|
|
|
::CGBitmapContextCreate(buffer.Elements(),
|
|
|
|
window.width, window.height, 8, window.width * 4,
|
|
|
|
cspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedFirst);
|
|
|
|
::CGColorSpaceRelease(cspace);
|
|
|
|
if (!cgBuffer) {
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
GWorldPtr gWorld;
|
|
|
|
if (::NewGWorldFromPtr(&gWorld, k32ARGBPixelFormat, &gwBounds, NULL, NULL, 0,
|
|
|
|
buffer.Elements(), window.width * 4) != noErr) {
|
|
|
|
::CGContextRelease(cgBuffer);
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.clipRect.right = window.width;
|
|
|
|
window.clipRect.bottom = window.height;
|
|
|
|
window.type = nsPluginWindowType_Drawable;
|
|
|
|
// Setting nsPluginPrint/NPPrint.print.embedPrint.window.window to
|
|
|
|
// &GWorldPtr and nsPluginPrint/NPPrint.print.embedPrint.platformPrint to
|
|
|
|
// GWorldPtr isn't any kind of standard (it's not documented anywhere).
|
|
|
|
// But that's what WebKit does. And it's what the Flash plugin (apparently
|
|
|
|
// the only NPAPI plugin on OS X to support printing) seems to expect. So
|
|
|
|
// we do the same. The Flash plugin uses the CoreGraphics drawing mode.
|
|
|
|
// But a GWorldPtr should be usable in either CoreGraphics or QuickDraw
|
|
|
|
// drawing mode. See bug 191046.
|
|
|
|
window.window = reinterpret_cast<nsPluginPort *>(&gWorld);
|
|
|
|
npprint.print.embedPrint.platformPrint = gWorld;
|
|
|
|
npprint.print.embedPrint.window = window;
|
|
|
|
nsresult rv = pi->Print(&npprint);
|
|
|
|
|
|
|
|
::CGContextSaveGState(cgContext);
|
|
|
|
::CGContextTranslateCTM(cgContext, 0.0f, float(window.height));
|
|
|
|
::CGContextScaleCTM(cgContext, 1.0f, -1.0f);
|
|
|
|
CGImageRef image = ::CGBitmapContextCreateImage(cgBuffer);
|
|
|
|
if (!image) {
|
|
|
|
::CGContextRestoreGState(cgContext);
|
|
|
|
::CGContextRelease(cgBuffer);
|
|
|
|
::DisposeGWorld(gWorld);
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
::CGContextDrawImage(cgContext,
|
|
|
|
::CGRectMake(0, 0, window.width, window.height),
|
|
|
|
image);
|
|
|
|
::CGImageRelease(image);
|
|
|
|
::CGContextRestoreGState(cgContext);
|
|
|
|
::CGContextRelease(cgBuffer);
|
|
|
|
|
|
|
|
::DisposeGWorld(gWorld);
|
|
|
|
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
#elif defined(XP_UNIX)
|
2008-03-05 23:06:46 -08:00
|
|
|
|
|
|
|
/* XXX this just flat-out doesn't work in a thebes world --
|
|
|
|
* RenderEPS is a no-op. So don't bother to do any work here.
|
|
|
|
*/
|
|
|
|
#if 0
|
2007-03-22 10:30:00 -07:00
|
|
|
/* UNIX does things completely differently:
|
|
|
|
* We call the plugin and it sends generated PostScript data into a
|
|
|
|
* file handle we provide. If the plugin returns with success we embed
|
|
|
|
* this PostScript code fragment into the PostScript job we send to the
|
|
|
|
* printer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("nsObjectFrame::Paint() start for X11 platforms\n"));
|
|
|
|
|
|
|
|
FILE *plugintmpfile = tmpfile();
|
|
|
|
if (!plugintmpfile) {
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("error: could not open tmp. file, errno=%d\n", errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send off print info to plugin */
|
|
|
|
NPPrintCallbackStruct npPrintInfo;
|
|
|
|
npPrintInfo.type = NP_PRINT;
|
|
|
|
npPrintInfo.fp = plugintmpfile;
|
|
|
|
npprint.print.embedPrint.platformPrint = (void *)&npPrintInfo;
|
|
|
|
/* aDirtyRect contains the right information for ps print */
|
|
|
|
window.x = aDirtyRect.x;
|
|
|
|
window.y = aDirtyRect.y;
|
|
|
|
window.width = aDirtyRect.width;
|
|
|
|
window.height = aDirtyRect.height;
|
|
|
|
npprint.print.embedPrint.window = window;
|
2008-09-20 06:42:03 -07:00
|
|
|
nsresult rv = pi->Print(&npprint);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("error: plugin returned failure %lx\n", (long)rv));
|
|
|
|
fclose(plugintmpfile);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send data to printer */
|
|
|
|
rv = aRenderingContext.RenderEPS(aDirtyRect, plugintmpfile);
|
|
|
|
|
|
|
|
fclose(plugintmpfile);
|
|
|
|
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG, ("plugin printing done, return code is %lx\n", (long)rv));
|
2008-03-05 23:06:46 -08:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-03-10 17:10:55 -07:00
|
|
|
#elif defined(XP_OS2)
|
|
|
|
void *hps = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS);
|
|
|
|
if (!hps)
|
|
|
|
return;
|
|
|
|
|
|
|
|
npprint.print.embedPrint.platformPrint = hps;
|
|
|
|
npprint.print.embedPrint.window = window;
|
|
|
|
// send off print info to plugin
|
2008-09-20 06:42:03 -07:00
|
|
|
pi->Print(&npprint);
|
2008-02-13 22:27:51 -08:00
|
|
|
#elif defined(XP_WIN)
|
|
|
|
|
|
|
|
/* On Windows, we use the win32 printing surface to print. This, in
|
|
|
|
* turn, uses the Cairo paginated surface, which in turn uses the
|
|
|
|
* meta surface to record all operations and then play them back.
|
|
|
|
* This doesn't work too well for plugins, because if plugins render
|
|
|
|
* directly into the DC, the meta surface won't have any knowledge
|
|
|
|
* of them, and so at the end when it actually does the replay step,
|
|
|
|
* it'll fill the background with white and draw over whatever was
|
|
|
|
* rendered before.
|
|
|
|
*
|
|
|
|
* So, to avoid this, we use PushGroup, which creates a new windows
|
|
|
|
* surface, the plugin renders to that, and then we use normal
|
|
|
|
* cairo methods to composite that in such that it's recorded using the
|
|
|
|
* meta surface.
|
|
|
|
*/
|
|
|
|
|
2008-03-05 23:06:46 -08:00
|
|
|
/* we'll already be translated into the right spot by gfxWindowsNativeDrawing */
|
|
|
|
window.x = 0;
|
|
|
|
window.y = 0;
|
|
|
|
window.width = presContext->AppUnitsToDevPixels(mRect.width);
|
|
|
|
window.height = presContext->AppUnitsToDevPixels(mRect.height);
|
|
|
|
|
2008-02-13 22:27:51 -08:00
|
|
|
gfxContext *ctx = aRenderingContext.ThebesContext();
|
|
|
|
|
|
|
|
ctx->Save();
|
|
|
|
|
2008-03-05 23:06:46 -08:00
|
|
|
/* Make sure plugins don't do any damage outside of where they're supposed to */
|
2008-02-13 22:27:51 -08:00
|
|
|
ctx->NewPath();
|
2008-10-29 22:28:25 -07:00
|
|
|
gfxRect r(window.x, window.y, window.width, window.height);
|
|
|
|
ctx->Rectangle(r);
|
2008-02-13 22:27:51 -08:00
|
|
|
ctx->Clip();
|
2008-03-05 23:06:46 -08:00
|
|
|
|
2008-10-29 22:28:25 -07:00
|
|
|
gfxWindowsNativeDrawing nativeDraw(ctx, r);
|
2008-02-13 22:27:51 -08:00
|
|
|
do {
|
|
|
|
HDC dc = nativeDraw.BeginNativeDrawing();
|
|
|
|
if (!dc)
|
|
|
|
return;
|
|
|
|
|
2008-10-29 22:28:25 -07:00
|
|
|
// XXX don't we need to call nativeDraw.TransformToNativeRect here?
|
2008-02-13 22:27:51 -08:00
|
|
|
npprint.print.embedPrint.platformPrint = dc;
|
|
|
|
npprint.print.embedPrint.window = window;
|
|
|
|
// send off print info to plugin
|
2008-09-20 06:42:03 -07:00
|
|
|
pi->Print(&npprint);
|
2008-02-13 22:27:51 -08:00
|
|
|
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
} while (nativeDraw.ShouldRenderAgain());
|
|
|
|
nativeDraw.PaintToContext();
|
|
|
|
|
|
|
|
ctx->Restore();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#else
|
|
|
|
|
2008-03-05 23:06:46 -08:00
|
|
|
// Get the offset of the DC
|
|
|
|
nsTransform2D* rcTransform;
|
|
|
|
aRenderingContext.GetCurrentTransform(rcTransform);
|
|
|
|
nsPoint origin;
|
|
|
|
rcTransform->GetTranslationCoord(&origin.x, &origin.y);
|
|
|
|
|
|
|
|
// set it all up
|
|
|
|
// XXX is windowless different?
|
|
|
|
window.x = presContext->AppUnitsToDevPixels(origin.x);
|
|
|
|
window.y = presContext->AppUnitsToDevPixels(origin.y);
|
|
|
|
window.width = presContext->AppUnitsToDevPixels(mRect.width);
|
|
|
|
window.height= presContext->AppUnitsToDevPixels(mRect.height);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// we need the native printer device context to pass to plugin
|
2008-02-13 22:27:51 -08:00
|
|
|
// NATIVE_WINDOWS_DC is a misnomer, it's whatever the native platform
|
|
|
|
// thing is.
|
2007-03-22 10:30:00 -07:00
|
|
|
void* dc;
|
|
|
|
dc = aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
|
2007-08-02 13:54:45 -07:00
|
|
|
if (!dc)
|
|
|
|
return; // no dc implemented so quit
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
npprint.print.embedPrint.platformPrint = dc;
|
|
|
|
npprint.print.embedPrint.window = window;
|
|
|
|
// send off print info to plugin
|
2008-09-20 06:42:03 -07:00
|
|
|
pi->Print(&npprint);
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
|
|
|
|
nsDidReflowStatus status = NS_FRAME_REFLOW_FINISHED; // should we use a special status?
|
|
|
|
frame->DidReflow(presContext,
|
|
|
|
nsnull, status); // DidReflow will take care of it
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
|
2008-07-06 19:49:38 -07:00
|
|
|
const nsRect& aDirtyRect, const nsPoint& aFramePt)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
// Screen painting code
|
|
|
|
#if defined(XP_MACOSX)
|
|
|
|
// delegate all painting to the plugin instance.
|
2008-02-20 03:33:27 -08:00
|
|
|
if (mInstanceOwner) {
|
|
|
|
if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics) {
|
2009-06-28 15:52:11 -07:00
|
|
|
PRInt32 appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
|
|
|
|
// Clip to the content area where the plugin should be drawn. If
|
|
|
|
// we don't do this, the plugin can draw outside its bounds.
|
|
|
|
nsRect content = GetContentRect() - GetPosition() + aFramePt;
|
|
|
|
nsIntRect contentPixels = content.ToNearestPixels(appUnitsPerDevPixel);
|
|
|
|
nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel);
|
|
|
|
nsIntRect clipPixels;
|
|
|
|
clipPixels.IntersectRect(contentPixels, dirtyPixels);
|
|
|
|
gfxRect nativeClipRect(clipPixels.x, clipPixels.y,
|
|
|
|
clipPixels.width, clipPixels.height);
|
2008-02-20 03:33:27 -08:00
|
|
|
gfxContext* ctx = aRenderingContext.ThebesContext();
|
2009-06-28 15:52:11 -07:00
|
|
|
|
|
|
|
gfxContextAutoSaveRestore save(ctx);
|
|
|
|
ctx->NewPath();
|
|
|
|
ctx->Rectangle(nativeClipRect);
|
|
|
|
ctx->Clip();
|
|
|
|
gfxPoint offset(contentPixels.x, contentPixels.y);
|
|
|
|
ctx->Translate(offset);
|
|
|
|
|
|
|
|
gfxQuartzNativeDrawing nativeDrawing(ctx, nativeClipRect - offset);
|
2008-02-20 03:33:27 -08:00
|
|
|
|
|
|
|
CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
|
|
|
|
if (!cgContext) {
|
|
|
|
NS_WARNING("null CGContextRef during PaintPlugin");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-02-26 01:09:05 -08:00
|
|
|
nsCOMPtr<nsIPluginInstance> inst;
|
|
|
|
GetPluginInstance(*getter_AddRefs(inst));
|
|
|
|
if (!inst) {
|
|
|
|
NS_WARNING("null plugin instance during PaintPlugin");
|
2008-10-30 10:40:53 -07:00
|
|
|
nativeDrawing.EndNativeDrawing();
|
2008-02-26 01:09:05 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsPluginWindow* window;
|
|
|
|
mInstanceOwner->GetWindow(window);
|
|
|
|
if (!window) {
|
|
|
|
NS_WARNING("null plugin window during PaintPlugin");
|
2008-10-30 10:40:53 -07:00
|
|
|
nativeDrawing.EndNativeDrawing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsPluginPort* pluginPortCopy = mInstanceOwner->GetPluginPortCopy();
|
|
|
|
if (!pluginPortCopy) {
|
|
|
|
NS_WARNING("null plugin port copy during PaintPlugin");
|
|
|
|
nativeDrawing.EndNativeDrawing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!mInstanceOwner->SetPluginPortAndDetectChange()) {
|
|
|
|
NS_WARNING("null plugin port during PaintPlugin");
|
|
|
|
nativeDrawing.EndNativeDrawing();
|
2008-02-26 01:09:05 -08:00
|
|
|
return;
|
|
|
|
}
|
2008-10-30 10:40:53 -07:00
|
|
|
// If gfxQuartzNativeDrawing hands out a CGContext different from the
|
|
|
|
// one set by SetPluginPortAndDetectChange(), we need to pass it to the
|
|
|
|
// plugin via SetWindow(). This will happen in nsPluginInstanceOwner::
|
|
|
|
// FixUpPluginWindow(), called from nsPluginInstanceOwner::Paint().
|
|
|
|
// (If SetPluginPortAndDetectChange() made any changes itself, this has
|
|
|
|
// already been detected in that method, and will likewise result in a
|
|
|
|
// call to SetWindow() from FixUpPluginWindow().)
|
2008-10-17 15:22:10 -07:00
|
|
|
if (window->window->cgPort.context != cgContext) {
|
2008-10-30 10:40:53 -07:00
|
|
|
window->window->cgPort.context = cgContext;
|
|
|
|
pluginPortCopy->cgPort.context = cgContext;
|
|
|
|
mInstanceOwner->SetPluginPortChanged(PR_TRUE);
|
2008-10-17 15:22:10 -07:00
|
|
|
}
|
2008-02-20 03:33:27 -08:00
|
|
|
|
2008-10-30 10:40:53 -07:00
|
|
|
mInstanceOwner->BeginCGPaint();
|
2009-08-26 17:29:47 -07:00
|
|
|
mInstanceOwner->Paint(nativeClipRect - offset);
|
2008-10-30 10:40:53 -07:00
|
|
|
mInstanceOwner->EndCGPaint();
|
2008-02-20 03:33:27 -08:00
|
|
|
|
|
|
|
nativeDrawing.EndNativeDrawing();
|
|
|
|
} else {
|
2009-06-28 15:52:11 -07:00
|
|
|
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
|
|
|
|
nsIRenderingContext::AutoPushTranslation
|
|
|
|
translate(&aRenderingContext, aFramePt.x, aFramePt.y);
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
// this rect is used only in the CoreGraphics drawing model
|
|
|
|
gfxRect tmpRect(0, 0, 0, 0);
|
|
|
|
mInstanceOwner->Paint(tmpRect);
|
2008-02-20 03:33:27 -08:00
|
|
|
}
|
|
|
|
}
|
2008-08-06 13:48:55 -07:00
|
|
|
#elif defined(MOZ_X11) || defined(MOZ_DFB)
|
2008-10-29 22:28:25 -07:00
|
|
|
if (mInstanceOwner) {
|
|
|
|
nsPluginWindow * window;
|
|
|
|
mInstanceOwner->GetWindow(window);
|
2009-02-25 07:25:12 -08:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
{
|
|
|
|
#else
|
2008-10-29 22:28:25 -07:00
|
|
|
if (window->type == nsPluginWindowType_Drawable) {
|
2009-02-25 07:25:12 -08:00
|
|
|
#endif
|
2008-10-29 22:28:25 -07:00
|
|
|
gfxRect frameGfxRect =
|
|
|
|
PresContext()->AppUnitsToGfxUnits(nsRect(aFramePt, GetSize()));
|
|
|
|
gfxRect dirtyGfxRect =
|
|
|
|
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
|
|
|
|
gfxContext* ctx = aRenderingContext.ThebesContext();
|
2008-07-06 19:49:38 -07:00
|
|
|
|
2008-10-29 22:28:25 -07:00
|
|
|
mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#elif defined(XP_WIN)
|
|
|
|
nsCOMPtr<nsIPluginInstance> inst;
|
|
|
|
GetPluginInstance(*getter_AddRefs(inst));
|
|
|
|
if (inst) {
|
|
|
|
gfxRect frameGfxRect =
|
|
|
|
PresContext()->AppUnitsToGfxUnits(nsRect(aFramePt, GetSize()));
|
|
|
|
gfxRect dirtyGfxRect =
|
|
|
|
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
|
|
|
|
gfxContext *ctx = aRenderingContext.ThebesContext();
|
|
|
|
gfxMatrix currentMatrix = ctx->CurrentMatrix();
|
|
|
|
|
|
|
|
if (ctx->UserToDevicePixelSnapped(frameGfxRect, PR_FALSE)) {
|
|
|
|
dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect);
|
|
|
|
ctx->IdentityMatrix();
|
|
|
|
}
|
|
|
|
dirtyGfxRect.RoundOut();
|
|
|
|
|
|
|
|
// Look if it's windowless
|
|
|
|
nsPluginWindow * window;
|
|
|
|
mInstanceOwner->GetWindow(window);
|
|
|
|
|
|
|
|
if (window->type == nsPluginWindowType_Drawable) {
|
|
|
|
// check if we need to call SetWindow with updated parameters
|
|
|
|
PRBool doupdatewindow = PR_FALSE;
|
|
|
|
// the offset of the DC
|
|
|
|
nsPoint origin;
|
|
|
|
|
|
|
|
gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
|
|
|
|
do {
|
|
|
|
HDC hdc = nativeDraw.BeginNativeDrawing();
|
|
|
|
if (!hdc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
RECT dest;
|
|
|
|
nativeDraw.TransformToNativeRect(frameGfxRect, dest);
|
|
|
|
RECT dirty;
|
|
|
|
nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty);
|
|
|
|
|
|
|
|
// XXX how can we be sure that window->window doesn't point to
|
|
|
|
// a dead DC and hdc has been reallocated at the same address?
|
|
|
|
if (reinterpret_cast<HDC>(window->window) != hdc ||
|
|
|
|
window->x != dest.left || window->y != dest.top) {
|
|
|
|
window->window = reinterpret_cast<nsPluginPort*>(hdc);
|
|
|
|
window->x = dest.left;
|
|
|
|
window->y = dest.top;
|
|
|
|
|
|
|
|
// Windowless plugins on windows need a special event to update their location, see bug 135737
|
|
|
|
// bug 271442: note, the rectangle we send is now purely the bounds of the plugin
|
|
|
|
// relative to the window it is contained in, which is useful for the plugin to correctly translate mouse coordinates
|
|
|
|
//
|
|
|
|
// this does not mesh with the comments for bug 135737 which imply that the rectangle
|
|
|
|
// must be clipped in some way to prevent the plugin attempting to paint over areas it shouldn't;
|
|
|
|
//
|
|
|
|
// since the two uses of the rectangle are mutually exclusive in some cases,
|
|
|
|
// and since I don't see any incorrect painting (at least with Flash and ViewPoint - the originator of 135737),
|
|
|
|
// it seems that windowless plugins are not relying on information here for clipping their drawing,
|
|
|
|
// and we can safely use this message to tell the plugin exactly where it is in all cases.
|
|
|
|
|
|
|
|
nsIntPoint origin = GetWindowOriginInPixels(PR_TRUE);
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
|
2008-10-29 22:28:25 -07:00
|
|
|
// XXX I don't think we can be certain that the location wrt to
|
|
|
|
// the window only changes when the location wrt to the drawable
|
|
|
|
// changes, but the hdc probably changes on every paint so
|
|
|
|
// doupdatewindow is rarely false, and there is not likely to be
|
|
|
|
// a problem.
|
|
|
|
if (mWindowlessRect != winlessRect) {
|
|
|
|
mWindowlessRect = winlessRect;
|
|
|
|
|
|
|
|
WINDOWPOS winpos;
|
|
|
|
memset(&winpos, 0, sizeof(winpos));
|
|
|
|
winpos.x = mWindowlessRect.x;
|
|
|
|
winpos.y = mWindowlessRect.y;
|
|
|
|
winpos.cx = mWindowlessRect.width;
|
|
|
|
winpos.cy = mWindowlessRect.height;
|
|
|
|
|
|
|
|
// finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
|
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
pluginEvent.event = WM_WINDOWPOSCHANGED;
|
|
|
|
pluginEvent.wParam = 0;
|
|
|
|
pluginEvent.lParam = (uint32)&winpos;
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
|
|
|
|
inst->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
}
|
|
|
|
|
|
|
|
inst->SetWindow(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
mInstanceOwner->Paint(dirty, hdc);
|
|
|
|
nativeDraw.EndNativeDrawing();
|
|
|
|
} while (nativeDraw.ShouldRenderAgain());
|
|
|
|
|
|
|
|
nativeDraw.PaintToContext();
|
|
|
|
} else if (!(ctx->GetFlags() & gfxContext::FLAG_DESTINED_FOR_SCREEN)) {
|
|
|
|
// Get PrintWindow dynamically since it's not present on Win2K,
|
|
|
|
// which we still support
|
|
|
|
typedef BOOL (WINAPI * PrintWindowPtr)
|
|
|
|
(HWND hwnd, HDC hdcBlt, UINT nFlags);
|
|
|
|
PrintWindowPtr printProc = nsnull;
|
|
|
|
HMODULE module = ::GetModuleHandleW(L"user32.dll");
|
|
|
|
if (module) {
|
|
|
|
printProc = reinterpret_cast<PrintWindowPtr>
|
|
|
|
(::GetProcAddress(module, "PrintWindow"));
|
|
|
|
}
|
2009-02-18 17:03:54 -08:00
|
|
|
// Disable this for Sun Java, it makes it go into a 100% cpu burn loop.
|
|
|
|
if (printProc && !mInstanceOwner->MatchPluginName("Java(TM) Platform")) {
|
2008-10-29 22:28:25 -07:00
|
|
|
HWND hwnd = reinterpret_cast<HWND>(window->window);
|
|
|
|
RECT rc;
|
|
|
|
GetWindowRect(hwnd, &rc);
|
|
|
|
nsRefPtr<gfxWindowsSurface> surface =
|
|
|
|
new gfxWindowsSurface(gfxIntSize(rc.right - rc.left, rc.bottom - rc.top));
|
|
|
|
|
|
|
|
if (surface && printProc) {
|
|
|
|
printProc(hwnd, surface->GetDC(), 0);
|
|
|
|
|
|
|
|
ctx->Translate(frameGfxRect.pos);
|
|
|
|
ctx->SetSource(surface);
|
|
|
|
gfxRect r = frameGfxRect.Intersect(dirtyGfxRect) - frameGfxRect.pos;
|
|
|
|
ctx->NewPath();
|
|
|
|
ctx->Rectangle(r);
|
|
|
|
ctx->Fill();
|
|
|
|
}
|
2008-07-06 19:49:38 -07:00
|
|
|
}
|
2007-07-02 20:33:13 -07:00
|
|
|
}
|
2008-10-29 22:28:25 -07:00
|
|
|
|
|
|
|
ctx->SetMatrix(currentMatrix);
|
|
|
|
}
|
|
|
|
#elif defined(XP_OS2)
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIPluginInstance> inst;
|
|
|
|
GetPluginInstance(*getter_AddRefs(inst));
|
|
|
|
if (inst) {
|
|
|
|
// Look if it's windowless
|
|
|
|
nsPluginWindow * window;
|
|
|
|
mInstanceOwner->GetWindow(window);
|
|
|
|
|
|
|
|
if (window->type == nsPluginWindowType_Drawable) {
|
2008-07-06 19:49:38 -07:00
|
|
|
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
|
2008-07-06 20:46:50 -07:00
|
|
|
nsIRenderingContext::AutoPushTranslation
|
2008-07-06 21:15:07 -07:00
|
|
|
translate(&aRenderingContext, aFramePt.x, aFramePt.y);
|
2008-07-06 19:49:38 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// check if we need to call SetWindow with updated parameters
|
|
|
|
PRBool doupdatewindow = PR_FALSE;
|
|
|
|
// the offset of the DC
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntPoint origin;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Layout now has an optimized way of painting. Now we always get
|
|
|
|
* a new drawing surface, sized to be just what's needed. Windowless
|
|
|
|
* plugins need a transform applied to their origin so they paint
|
|
|
|
* in the right place. Since |SetWindow| is no longer being used
|
|
|
|
* to tell the plugin where it is, we dispatch a NPWindow through
|
|
|
|
* |HandleEvent| to tell the plugin when its window moved
|
|
|
|
*/
|
2008-06-03 15:25:31 -07:00
|
|
|
gfxContext *ctx = aRenderingContext.ThebesContext();
|
2008-10-29 22:28:25 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
gfxMatrix ctxMatrix = ctx->CurrentMatrix();
|
|
|
|
if (ctxMatrix.HasNonTranslation()) {
|
|
|
|
// soo; in the future, we should be able to render
|
|
|
|
// the object content to an offscreen DC, and then
|
|
|
|
// composite it in with the right transforms.
|
|
|
|
|
|
|
|
// But, we don't bother doing that, because we don't
|
|
|
|
// have the event handling story figured out yet.
|
|
|
|
// Instead, let's just bail.
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
origin.x = NSToIntRound(float(ctxMatrix.GetTranslation().x));
|
|
|
|
origin.y = NSToIntRound(float(ctxMatrix.GetTranslation().y));
|
|
|
|
|
|
|
|
/* Need to force the clip to be set */
|
|
|
|
ctx->UpdateSurfaceClip();
|
|
|
|
|
|
|
|
/* Set the device offsets as appropriate, for whatever our current group offsets might be */
|
|
|
|
gfxFloat xoff, yoff;
|
|
|
|
nsRefPtr<gfxASurface> surf = ctx->CurrentSurface(&xoff, &yoff);
|
|
|
|
|
2008-03-07 16:58:57 -08:00
|
|
|
if (surf->CairoStatus() != 0) {
|
|
|
|
NS_WARNING("Plugin is being asked to render to a surface that's in error!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-10 17:10:55 -07:00
|
|
|
// check if we need to update the PS
|
|
|
|
HPS hps = (HPS)aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_OS2_PS);
|
|
|
|
if (reinterpret_cast<HPS>(window->window) != hps) {
|
|
|
|
window->window = reinterpret_cast<nsPluginPort*>(hps);
|
|
|
|
doupdatewindow = PR_TRUE;
|
|
|
|
}
|
|
|
|
LONG lPSid = GpiSavePS(hps);
|
|
|
|
RECTL rclViewport;
|
|
|
|
if (GpiQueryDevice(hps) != NULLHANDLE) { // ensure that we have an associated HDC
|
|
|
|
if (GpiQueryPageViewport(hps, &rclViewport)) {
|
|
|
|
rclViewport.xLeft += (LONG)xoff;
|
|
|
|
rclViewport.xRight += (LONG)xoff;
|
|
|
|
rclViewport.yBottom += (LONG)yoff;
|
|
|
|
rclViewport.yTop += (LONG)yoff;
|
|
|
|
GpiSetPageViewport(hps, &rclViewport);
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if ((window->x != origin.x) || (window->y != origin.y)) {
|
|
|
|
window->x = origin.x;
|
|
|
|
window->y = origin.y;
|
|
|
|
doupdatewindow = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if our location or visible area has changed, we need to tell the plugin
|
|
|
|
if (doupdatewindow) {
|
|
|
|
inst->SetWindow(window);
|
|
|
|
}
|
|
|
|
|
2008-03-10 17:10:55 -07:00
|
|
|
mInstanceOwner->Paint(aDirtyRect, hps);
|
|
|
|
if (lPSid >= 1) {
|
|
|
|
GpiRestorePS(hps, lPSid);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
surf->MarkDirty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
|
|
|
|
nsGUIEvent* anEvent,
|
|
|
|
nsEventStatus* anEventStatus)
|
|
|
|
{
|
2009-08-26 17:29:47 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(anEvent);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(anEventStatus);
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
if (!mInstanceOwner)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
mInstanceOwner->ConsiderNewEventloopNestingLevel();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (anEvent->message == NS_PLUGIN_ACTIVATE) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(GetContent());
|
|
|
|
if (fm && elem)
|
|
|
|
return fm->SetFocus(elem, 0);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-12-14 19:54:54 -08:00
|
|
|
if (mInstanceOwner->SendNativeEvents() && NS_IS_PLUGIN_EVENT(anEvent)) {
|
|
|
|
*anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifdef XP_WIN
|
|
|
|
rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
|
|
|
|
return rv;
|
|
|
|
#endif
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
// we want to process native mouse enter events in the cocoa event model
|
|
|
|
if (anEvent->message == NS_MOUSE_ENTER && mInstanceOwner->GetEventModel() == NPEventModelCocoa) {
|
|
|
|
*anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
switch (anEvent->message) {
|
|
|
|
case NS_DESTROY:
|
|
|
|
mInstanceOwner->CancelTimer();
|
|
|
|
break;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
case NS_ACTIVATE:
|
|
|
|
case NS_DEACTIVATE:
|
2007-03-22 10:30:00 -07:00
|
|
|
*anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// instead of using an event listener, we can dispatch events to plugins directly.
|
|
|
|
rv = nsObjectFrameSuper::HandleEvent(aPresContext, anEvent, anEventStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2008-06-27 12:37:21 -07:00
|
|
|
nsresult
|
|
|
|
nsObjectFrame::GetPluginInstance(nsIPluginInstance*& aPluginInstance)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
aPluginInstance = nsnull;
|
|
|
|
|
|
|
|
if (!mInstanceOwner)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
return mInstanceOwner->GetInstance(aPluginInstance);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsObjectFrame::PrepareInstanceOwner()
|
|
|
|
{
|
2008-03-07 13:32:49 -08:00
|
|
|
nsWeakFrame weakFrame(this);
|
|
|
|
|
2007-09-25 13:41:07 -07:00
|
|
|
// First, have to stop any possibly running plugins.
|
|
|
|
StopPluginInternal(PR_FALSE);
|
|
|
|
|
2008-03-07 13:32:49 -08:00
|
|
|
if (!weakFrame.IsAlive()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(!mInstanceOwner, "Must not have an instance owner here");
|
|
|
|
|
|
|
|
mInstanceOwner = new nsPluginInstanceOwner();
|
2008-02-28 18:06:00 -08:00
|
|
|
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("Created new instance owner %p for frame %p\n", mInstanceOwner.get(),
|
|
|
|
this));
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mInstanceOwner)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
// Note, |this| may very well be gone after this call.
|
|
|
|
return mInstanceOwner->Init(PresContext(), this, GetContent());
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsObjectFrame::Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamListener)
|
|
|
|
{
|
2008-05-06 13:49:30 -07:00
|
|
|
if (mPreventInstantiation) {
|
2007-12-03 14:09:00 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
// Note: If PrepareInstanceOwner() returns an error, |this| may very
|
|
|
|
// well be deleted already.
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv = PrepareInstanceOwner();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2009-06-25 14:06:54 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
mInstanceOwner->SetPluginHost(pluginHost);
|
|
|
|
|
|
|
|
// This must be done before instantiating the plugin
|
|
|
|
FixupWindow(mRect.Size());
|
|
|
|
|
2008-06-27 12:37:21 -07:00
|
|
|
nsWeakFrame weakFrame(this);
|
|
|
|
|
2008-05-06 13:49:30 -07:00
|
|
|
NS_ASSERTION(!mPreventInstantiation, "Say what?");
|
|
|
|
mPreventInstantiation = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = pluginHost->InstantiatePluginForChannel(aChannel, mInstanceOwner, aStreamListener);
|
2008-06-27 12:37:21 -07:00
|
|
|
|
|
|
|
if (!weakFrame.IsAlive()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2008-05-06 13:49:30 -07:00
|
|
|
NS_ASSERTION(mPreventInstantiation,
|
|
|
|
"Instantiation should still be prevented!");
|
|
|
|
mPreventInstantiation = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsObjectFrame::Instantiate(const char* aMimeType, nsIURI* aURI)
|
|
|
|
{
|
2008-02-28 18:06:00 -08:00
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("nsObjectFrame::Instantiate(%s) called on frame %p\n", aMimeType,
|
|
|
|
this));
|
|
|
|
|
2008-05-06 13:49:30 -07:00
|
|
|
if (mPreventInstantiation) {
|
2007-12-03 14:09:00 -08:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-02-28 18:06:00 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(aMimeType || aURI, "Need a type or a URI!");
|
2008-02-28 18:06:00 -08:00
|
|
|
|
|
|
|
// Note: If PrepareInstanceOwner() returns an error, |this| may very
|
|
|
|
// well be deleted already.
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv = PrepareInstanceOwner();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2008-06-27 12:37:21 -07:00
|
|
|
nsWeakFrame weakFrame(this);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// This must be done before instantiating the plugin
|
|
|
|
FixupWindow(mRect.Size());
|
|
|
|
|
|
|
|
// get the nsIPluginHost service
|
2009-06-25 14:06:54 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> pluginHost(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &rv));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
mInstanceOwner->SetPluginHost(pluginHost);
|
|
|
|
|
2008-10-04 13:00:09 -07:00
|
|
|
NS_ASSERTION(!mPreventInstantiation, "Say what?");
|
2008-05-06 13:49:30 -07:00
|
|
|
mPreventInstantiation = PR_TRUE;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = InstantiatePlugin(pluginHost, aMimeType, aURI);
|
|
|
|
|
2008-06-27 12:37:21 -07:00
|
|
|
if (!weakFrame.IsAlive()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// finish up
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2007-08-02 14:15:05 -07:00
|
|
|
TryNotifyContentObjectWrapper();
|
2008-06-27 12:37:21 -07:00
|
|
|
|
|
|
|
if (!weakFrame.IsAlive()) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2007-08-20 10:40:08 -07:00
|
|
|
CallSetWindow();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-05-06 13:49:30 -07:00
|
|
|
NS_ASSERTION(mPreventInstantiation,
|
|
|
|
"Instantiation should still be prevented!");
|
|
|
|
|
|
|
|
mPreventInstantiation = PR_FALSE;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2007-08-02 14:15:05 -07:00
|
|
|
void
|
|
|
|
nsObjectFrame::TryNotifyContentObjectWrapper()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPluginInstance> inst;
|
|
|
|
mInstanceOwner->GetInstance(*getter_AddRefs(inst));
|
|
|
|
if (inst) {
|
|
|
|
// The plugin may have set up new interfaces; we need to mess with our JS
|
|
|
|
// wrapper. Note that we DO NOT want to call this if there is no plugin
|
|
|
|
// instance! That would just reenter Instantiate(), trying to create
|
|
|
|
// said plugin instance.
|
|
|
|
NotifyContentObjectWrapper();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
class nsStopPluginRunnable : public nsRunnable, public nsITimerCallback
|
2007-06-27 17:15:11 -07:00
|
|
|
{
|
2007-08-13 13:47:04 -07:00
|
|
|
public:
|
2008-03-25 09:56:04 -07:00
|
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
nsStopPluginRunnable(nsPluginInstanceOwner *aInstanceOwner)
|
|
|
|
: mInstanceOwner(aInstanceOwner)
|
|
|
|
{
|
2008-03-25 09:56:04 -07:00
|
|
|
NS_ASSERTION(aInstanceOwner, "need an owner");
|
2007-08-13 13:47:04 -07:00
|
|
|
}
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
// nsRunnable
|
2007-08-13 13:47:04 -07:00
|
|
|
NS_IMETHOD Run();
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
// nsITimerCallback
|
|
|
|
NS_IMETHOD Notify(nsITimer *timer);
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
private:
|
2008-03-25 09:56:04 -07:00
|
|
|
nsCOMPtr<nsITimer> mTimer;
|
2007-08-13 13:47:04 -07:00
|
|
|
nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
|
|
|
};
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
|
|
|
|
|
2008-07-06 19:49:38 -07:00
|
|
|
#ifdef XP_WIN
|
2008-04-08 23:28:23 -07:00
|
|
|
static const char*
|
|
|
|
GetMIMEType(nsIPluginInstance *aPluginInstance)
|
|
|
|
{
|
2009-06-28 16:43:19 -07:00
|
|
|
if (aPluginInstance) {
|
2009-07-13 09:27:46 -07:00
|
|
|
const char* mime = nsnull;
|
2009-06-28 16:43:19 -07:00
|
|
|
if (NS_SUCCEEDED(aPluginInstance->GetMIMEType(&mime)) && mime)
|
2008-04-08 23:28:23 -07:00
|
|
|
return mime;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2008-07-06 19:49:38 -07:00
|
|
|
#endif
|
2008-04-08 23:28:23 -07:00
|
|
|
|
2008-04-16 13:06:48 -07:00
|
|
|
static PRBool
|
|
|
|
DoDelayedStop(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop)
|
|
|
|
{
|
2008-07-12 03:28:50 -07:00
|
|
|
// Don't delay stopping QuickTime (bug 425157), Flip4Mac (bug 426524),
|
2009-05-14 19:16:27 -07:00
|
|
|
// XStandard (bug 430219), CMISS Zinc (bug 429604).
|
2008-07-12 03:28:50 -07:00
|
|
|
if (aDelayedStop
|
2009-05-14 19:16:27 -07:00
|
|
|
#if !(defined XP_WIN || defined MOZ_X11)
|
2008-12-14 19:54:54 -08:00
|
|
|
&& !aInstanceOwner->MatchPluginName("QuickTime")
|
|
|
|
&& !aInstanceOwner->MatchPluginName("Flip4Mac")
|
|
|
|
&& !aInstanceOwner->MatchPluginName("XStandard plugin")
|
|
|
|
&& !aInstanceOwner->MatchPluginName("CMISS Zinc Plugin")
|
2008-07-12 03:28:50 -07:00
|
|
|
#endif
|
|
|
|
) {
|
2008-04-16 13:06:48 -07:00
|
|
|
nsCOMPtr<nsIRunnable> evt = new nsStopPluginRunnable(aInstanceOwner);
|
|
|
|
NS_DispatchToCurrentThread(evt);
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
static void
|
2008-03-19 12:43:10 -07:00
|
|
|
DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop)
|
2007-08-13 13:47:04 -07:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPluginInstance> inst;
|
|
|
|
aInstanceOwner->GetInstance(*getter_AddRefs(inst));
|
|
|
|
if (inst) {
|
|
|
|
nsPluginWindow *win;
|
|
|
|
aInstanceOwner->GetWindow(win);
|
|
|
|
nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
|
|
|
|
nsCOMPtr<nsIPluginInstance> nullinst;
|
|
|
|
|
|
|
|
PRBool doCache = PR_TRUE;
|
|
|
|
PRBool doCallSetWindowAfterDestroy = PR_FALSE;
|
|
|
|
|
|
|
|
// first, determine if the plugin wants to be cached
|
|
|
|
inst->GetValue(nsPluginInstanceVariable_DoCacheBool, (void *)&doCache);
|
|
|
|
if (!doCache) {
|
|
|
|
// then determine if the plugin wants Destroy to be called after
|
|
|
|
// Set Window. This is for bug 50547.
|
|
|
|
inst->GetValue(nsPluginInstanceVariable_CallSetWindowAfterDestroyBool,
|
|
|
|
(void *)&doCallSetWindowAfterDestroy);
|
|
|
|
if (doCallSetWindowAfterDestroy) {
|
|
|
|
inst->Stop();
|
|
|
|
|
|
|
|
if (window)
|
|
|
|
window->CallSetWindow(nullinst);
|
|
|
|
else
|
|
|
|
inst->SetWindow(nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (window)
|
|
|
|
window->CallSetWindow(nullinst);
|
|
|
|
else
|
|
|
|
inst->SetWindow(nsnull);
|
|
|
|
|
2008-04-16 13:06:48 -07:00
|
|
|
if (DoDelayedStop(aInstanceOwner, aDelayedStop))
|
2008-03-13 20:31:35 -07:00
|
|
|
return;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
inst->Stop();
|
|
|
|
}
|
2007-08-13 13:47:04 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (window)
|
|
|
|
window->CallSetWindow(nullinst);
|
|
|
|
else
|
|
|
|
inst->SetWindow(nsnull);
|
2007-06-27 17:15:11 -07:00
|
|
|
|
2008-04-16 13:06:48 -07:00
|
|
|
if (DoDelayedStop(aInstanceOwner, aDelayedStop))
|
2008-03-13 20:31:35 -07:00
|
|
|
return;
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
inst->Stop();
|
2007-06-27 17:15:11 -07:00
|
|
|
}
|
|
|
|
|
2009-06-25 14:06:54 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> pluginHost = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
2007-08-13 13:47:04 -07:00
|
|
|
if (pluginHost)
|
|
|
|
pluginHost->StopPluginInstance(inst);
|
|
|
|
|
|
|
|
// the frame is going away along with its widget so tell the
|
|
|
|
// window to forget its widget too
|
|
|
|
if (window)
|
|
|
|
window->SetPluginWidget(nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
aInstanceOwner->Destroy();
|
|
|
|
}
|
|
|
|
|
2008-03-25 09:56:04 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsStopPluginRunnable::Notify(nsITimer *aTimer)
|
|
|
|
{
|
|
|
|
return Run();
|
|
|
|
}
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsStopPluginRunnable::Run()
|
|
|
|
{
|
2008-03-25 09:56:04 -07:00
|
|
|
// InitWithCallback calls Release before AddRef so we need to hold a
|
|
|
|
// strong ref on 'this' since we fall through to this scope if it fails.
|
|
|
|
nsCOMPtr<nsITimerCallback> kungFuDeathGrip = this;
|
|
|
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
|
|
|
if (appShell) {
|
|
|
|
PRUint32 currentLevel = 0;
|
|
|
|
appShell->GetEventloopNestingLevel(¤tLevel);
|
|
|
|
if (currentLevel > mInstanceOwner->GetLastEventloopNestingLevel()) {
|
|
|
|
if (!mTimer)
|
|
|
|
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
if (mTimer) {
|
2008-03-26 17:24:31 -07:00
|
|
|
// Fire 100ms timer to try to tear down this plugin as quickly as
|
|
|
|
// possible once the nesting level comes back down.
|
|
|
|
nsresult rv = mTimer->InitWithCallback(this, 100, nsITimer::TYPE_ONE_SHOT);
|
2008-03-25 09:56:04 -07:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_ERROR("Failed to setup a timer to stop the plugin later (at a safe "
|
|
|
|
"time). Stopping the plugin now, this might crash.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mTimer = nsnull;
|
|
|
|
|
2008-03-19 12:43:10 -07:00
|
|
|
DoStopPlugin(mInstanceOwner, PR_FALSE);
|
2007-08-13 13:47:04 -07:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::StopPlugin()
|
|
|
|
{
|
2008-04-08 23:28:23 -07:00
|
|
|
PRBool delayedStop = PR_FALSE;
|
2008-03-25 09:56:04 -07:00
|
|
|
#ifdef XP_WIN
|
|
|
|
nsCOMPtr<nsIPluginInstance> inst;
|
|
|
|
if (mInstanceOwner)
|
|
|
|
mInstanceOwner->GetInstance(*getter_AddRefs(inst));
|
|
|
|
if (inst) {
|
2008-04-08 23:28:23 -07:00
|
|
|
// Delayed stop for Real plugin only; see bug 420886, 426852.
|
|
|
|
const char* pluginType = ::GetMIMEType(inst);
|
|
|
|
delayedStop = strcmp(pluginType, "audio/x-pn-realaudio-plugin") == 0;
|
2008-03-25 09:56:04 -07:00
|
|
|
}
|
|
|
|
#endif
|
2008-04-08 23:28:23 -07:00
|
|
|
StopPluginInternal(delayedStop);
|
2007-08-13 13:47:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::StopPluginInternal(PRBool aDelayedStop)
|
|
|
|
{
|
2008-03-07 13:32:49 -08:00
|
|
|
if (!mInstanceOwner) {
|
2007-08-13 13:47:04 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-03-07 13:32:49 -08:00
|
|
|
// Transfer the reference to the instance owner onto the stack so
|
|
|
|
// that if we do end up re-entering this code, or if we unwind back
|
|
|
|
// here witha deleted frame (this), we can still continue to stop
|
|
|
|
// the plugin. Note that due to that, the ordering of the code in
|
|
|
|
// this function is extremely important.
|
|
|
|
|
|
|
|
nsRefPtr<nsPluginInstanceOwner> owner;
|
|
|
|
owner.swap(mInstanceOwner);
|
|
|
|
|
|
|
|
// Make sure that our windowless rect has been zeroed out, so if we
|
|
|
|
// get reinstantiated we'll send the right messages to the plug-in.
|
|
|
|
mWindowlessRect.Empty();
|
|
|
|
|
2008-05-06 13:49:30 -07:00
|
|
|
PRBool oldVal = mPreventInstantiation;
|
|
|
|
mPreventInstantiation = PR_TRUE;
|
|
|
|
|
|
|
|
nsWeakFrame weakFrame(this);
|
|
|
|
|
2009-05-14 19:16:27 -07:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_X11)
|
2009-07-21 17:45:00 -07:00
|
|
|
if (aDelayedStop && mWidget) {
|
2007-08-13 13:47:04 -07:00
|
|
|
// If we're asked to do a delayed stop it means we're stopping the
|
2009-07-21 17:45:00 -07:00
|
|
|
// plugin because we're destroying the frame. In that case, disown
|
|
|
|
// the widget.
|
|
|
|
GetView()->DetachWidgetEventHandler(mWidget);
|
|
|
|
mWidget = nsnull;
|
2008-03-07 13:32:49 -08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// From this point on, |this| could have been deleted, so don't
|
|
|
|
// touch it!
|
|
|
|
owner->PrepareToStop(aDelayedStop);
|
|
|
|
|
2008-03-19 12:43:10 -07:00
|
|
|
DoStopPlugin(owner, aDelayedStop);
|
2007-08-13 13:47:04 -07:00
|
|
|
|
2008-05-06 13:49:30 -07:00
|
|
|
// If |this| is still alive, reset mPreventInstantiation.
|
|
|
|
if (weakFrame.IsAlive()) {
|
|
|
|
NS_ASSERTION(mPreventInstantiation,
|
|
|
|
"Instantiation should still be prevented!");
|
|
|
|
|
|
|
|
mPreventInstantiation = oldVal;
|
|
|
|
}
|
|
|
|
|
2007-08-13 13:47:04 -07:00
|
|
|
// Break relationship between frame and plugin instance owner
|
2008-03-07 13:32:49 -08:00
|
|
|
owner->SetOwner(nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsObjectFrame::NotifyContentObjectWrapper()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDocument> doc = mContent->GetDocument();
|
|
|
|
if (!doc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject();
|
|
|
|
if (!sgo)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsIScriptContext *scx = sgo->GetContext();
|
|
|
|
if (!scx)
|
|
|
|
return;
|
|
|
|
|
|
|
|
JSContext *cx = (JSContext *)scx->GetNativeContext();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
|
|
|
|
nsContentUtils::XPConnect()->
|
|
|
|
GetWrappedNativeOfNativeObject(cx, sgo->GetGlobalJSObject(), mContent,
|
|
|
|
NS_GET_IID(nsISupports),
|
|
|
|
getter_AddRefs(wrapper));
|
|
|
|
|
|
|
|
if (!wrapper) {
|
2008-03-14 16:08:57 -07:00
|
|
|
// Nothing to do here if there's no wrapper for mContent. The proto
|
|
|
|
// chain will be fixed appropriately when the wrapper is created.
|
2007-03-22 10:30:00 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSObject *obj = nsnull;
|
|
|
|
nsresult rv = wrapper->GetJSObject(&obj);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return;
|
|
|
|
|
2008-03-14 16:08:57 -07:00
|
|
|
nsHTMLPluginObjElementSH::SetupProtoChain(wrapper, cx, obj);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
nsIObjectFrame *
|
|
|
|
nsObjectFrame::GetNextObjectFrame(nsPresContext* aPresContext, nsIFrame* aRoot)
|
|
|
|
{
|
|
|
|
nsIFrame* child = aRoot->GetFirstChild(nsnull);
|
|
|
|
|
|
|
|
while (child) {
|
2009-01-12 11:20:59 -08:00
|
|
|
nsIObjectFrame* outFrame = do_QueryFrame(child);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (outFrame) {
|
|
|
|
nsCOMPtr<nsIPluginInstance> pi;
|
|
|
|
outFrame->GetPluginInstance(*getter_AddRefs(pi)); // make sure we have a REAL plugin
|
|
|
|
if (pi)
|
|
|
|
return outFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
outFrame = GetNextObjectFrame(aPresContext, child);
|
|
|
|
if (outFrame)
|
|
|
|
return outFrame;
|
|
|
|
child = child->GetNextSibling();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame*
|
|
|
|
NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|
|
|
{
|
|
|
|
return new (aPresShell) nsObjectFrame(aContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// nsPluginDOMContextMenuListener class implementation
|
|
|
|
|
|
|
|
nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPluginDOMContextMenuListener::~nsPluginDOMContextMenuListener()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-04-07 23:18:35 -07:00
|
|
|
NS_IMPL_ISUPPORTS3(nsPluginDOMContextMenuListener,
|
|
|
|
nsIDOMContextMenuListener,
|
|
|
|
nsIDOMEventListener,
|
|
|
|
nsIEventListener)
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPluginDOMContextMenuListener::ContextMenu(nsIDOMEvent* aContextMenuEvent)
|
|
|
|
{
|
|
|
|
aContextMenuEvent->PreventDefault(); // consume event
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginDOMContextMenuListener::Init(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> receiver(do_QueryInterface(aContent));
|
|
|
|
if (receiver) {
|
|
|
|
receiver->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, PR_TRUE);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginDOMContextMenuListener::Destroy(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
// Unregister context menu listener
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> receiver(do_QueryInterface(aContent));
|
|
|
|
if (receiver) {
|
|
|
|
receiver->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
//plugin instance owner
|
|
|
|
|
|
|
|
nsPluginInstanceOwner::nsPluginInstanceOwner()
|
|
|
|
{
|
|
|
|
// create nsPluginNativeWindow object, it is derived from nsPluginWindow
|
|
|
|
// struct and allows to manipulate native window procedure
|
2009-06-25 14:06:54 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> ph = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
2009-06-30 13:49:04 -07:00
|
|
|
if (ph)
|
|
|
|
ph->NewPluginNativeWindow(&mPluginWindow);
|
2007-03-22 10:30:00 -07:00
|
|
|
else
|
|
|
|
mPluginWindow = nsnull;
|
|
|
|
|
|
|
|
mOwner = nsnull;
|
|
|
|
mTagText = nsnull;
|
2008-10-30 10:40:53 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
memset(&mPluginPortCopy, 0, sizeof(nsPluginPort));
|
|
|
|
mInCGPaintLevel = 0;
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
mContentFocused = PR_FALSE;
|
|
|
|
mWidgetVisible = PR_TRUE;
|
2008-10-30 10:40:53 -07:00
|
|
|
mPluginPortChanged = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
mNumCachedAttrs = 0;
|
|
|
|
mNumCachedParams = 0;
|
|
|
|
mCachedAttrParamNames = nsnull;
|
|
|
|
mCachedAttrParamValues = nsnull;
|
2007-08-13 13:47:04 -07:00
|
|
|
mDestroyWidget = PR_FALSE;
|
2008-12-03 01:30:40 -08:00
|
|
|
mTimerCanceled = PR_TRUE;
|
2008-02-28 18:06:00 -08:00
|
|
|
|
2009-02-25 07:25:12 -08:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
mLastPoint = nsIntPoint(0,0);
|
|
|
|
#endif
|
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("nsPluginInstanceOwner %p created\n", this));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsPluginInstanceOwner::~nsPluginInstanceOwner()
|
|
|
|
{
|
|
|
|
PRInt32 cnt;
|
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("nsPluginInstanceOwner %p deleted\n", this));
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// shut off the timer.
|
2008-12-03 01:30:40 -08:00
|
|
|
CancelTimer();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
mOwner = nsnull;
|
|
|
|
|
|
|
|
for (cnt = 0; cnt < (mNumCachedAttrs + 1 + mNumCachedParams); cnt++) {
|
|
|
|
if (mCachedAttrParamNames && mCachedAttrParamNames[cnt]) {
|
2009-04-05 05:57:07 -07:00
|
|
|
NS_Free(mCachedAttrParamNames[cnt]);
|
2007-03-22 10:30:00 -07:00
|
|
|
mCachedAttrParamNames[cnt] = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCachedAttrParamValues && mCachedAttrParamValues[cnt]) {
|
2009-04-05 05:57:07 -07:00
|
|
|
NS_Free(mCachedAttrParamValues[cnt]);
|
2007-03-22 10:30:00 -07:00
|
|
|
mCachedAttrParamValues[cnt] = nsnull;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCachedAttrParamNames) {
|
|
|
|
PR_Free(mCachedAttrParamNames);
|
|
|
|
mCachedAttrParamNames = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCachedAttrParamValues) {
|
|
|
|
PR_Free(mCachedAttrParamValues);
|
|
|
|
mCachedAttrParamValues = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mTagText) {
|
|
|
|
NS_Free(mTagText);
|
|
|
|
mTagText = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
// clean up plugin native window object
|
2009-06-25 14:06:54 -07:00
|
|
|
nsCOMPtr<nsIPluginHost> ph = do_GetService(MOZ_PLUGIN_HOST_CONTRACTID);
|
2009-06-30 13:49:04 -07:00
|
|
|
if (ph) {
|
|
|
|
ph->DeletePluginNativeWindow(mPluginWindow);
|
2007-03-22 10:30:00 -07:00
|
|
|
mPluginWindow = nsnull;
|
|
|
|
}
|
2009-01-25 22:00:12 -08:00
|
|
|
|
|
|
|
if (mInstance) {
|
2009-06-29 11:53:52 -07:00
|
|
|
mInstance->InvalidateOwner();
|
2009-01-25 22:00:12 -08:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* nsISupports Implementation
|
|
|
|
*/
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF(nsPluginInstanceOwner)
|
|
|
|
NS_IMPL_RELEASE(nsPluginInstanceOwner)
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsPluginInstanceOwner)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIPluginTagInfo)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIEventListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseMotionListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIScrollPositionListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMMouseListener)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPluginInstanceOwner)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
2009-02-24 16:28:35 -08:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsPluginInstanceOwner::SetInstance(nsIPluginInstance *aInstance)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2009-02-24 16:28:35 -08:00
|
|
|
NS_ASSERTION(!mInstance || !aInstance, "mInstance should only be set once!");
|
2009-01-25 22:00:12 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
mInstance = aInstance;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetWindow(nsPluginWindow *&aWindow)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mPluginWindow, "the plugin window object being returned is null");
|
|
|
|
aWindow = mPluginWindow;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetMode(nsPluginMode *aMode)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
nsresult rv = GetDocument(getter_AddRefs(doc));
|
|
|
|
nsCOMPtr<nsIPluginDocument> pDoc (do_QueryInterface(doc));
|
|
|
|
|
|
|
|
if (pDoc) {
|
|
|
|
*aMode = nsPluginMode_Full;
|
|
|
|
} else {
|
|
|
|
*aMode = nsPluginMode_Embedded;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetAttributes(PRUint16& n,
|
|
|
|
const char*const*& names,
|
|
|
|
const char*const*& values)
|
|
|
|
{
|
|
|
|
nsresult rv = EnsureCachedAttrParamArrays();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
n = mNumCachedAttrs;
|
|
|
|
names = (const char **)mCachedAttrParamNames;
|
|
|
|
values = (const char **)mCachedAttrParamValues;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetAttribute(const char* name, const char* *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(name);
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
|
|
|
|
nsresult rv = EnsureCachedAttrParamArrays();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
*result = nsnull;
|
|
|
|
|
|
|
|
for (int i = 0; i < mNumCachedAttrs; i++) {
|
|
|
|
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
|
|
|
|
*result = mCachedAttrParamValues[i];
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetDOMElement(nsIDOMElement* *result)
|
|
|
|
{
|
|
|
|
return CallQueryInterface(mContent, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetInstance(nsIPluginInstance *&aInstance)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(aInstance = mInstance);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetURL(const char *aURL, const char *aTarget, void *aPostData, PRUint32 aPostDataLen, void *aHeadersData,
|
|
|
|
PRUint32 aHeadersDataLen, PRBool isFile)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(mOwner,NS_ERROR_NULL_POINTER);
|
|
|
|
|
2007-07-11 06:05:05 -07:00
|
|
|
if (mContent->IsEditable()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// the container of the pres context will give us the link handler
|
2007-03-30 14:11:41 -07:00
|
|
|
nsCOMPtr<nsISupports> container = mOwner->PresContext()->GetContainer();
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_TRUE(container,NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsILinkHandler> lh = do_QueryInterface(container);
|
|
|
|
NS_ENSURE_TRUE(lh, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
nsAutoString unitarget;
|
|
|
|
unitarget.AssignASCII(aTarget); // XXX could this be nonascii?
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
|
|
|
|
|
|
|
|
// Create an absolute URL
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, baseURI);
|
|
|
|
|
|
|
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIInputStream> postDataStream;
|
|
|
|
nsCOMPtr<nsIInputStream> headersDataStream;
|
|
|
|
|
|
|
|
// deal with post data, either in a file or raw data, and any headers
|
|
|
|
if (aPostData) {
|
|
|
|
|
|
|
|
rv = NS_NewPluginPostDataStream(getter_AddRefs(postDataStream), (const char *)aPostData, aPostDataLen, isFile);
|
|
|
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin post data stream");
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
if (aHeadersData) {
|
|
|
|
rv = NS_NewPluginPostDataStream(getter_AddRefs(headersDataStream),
|
|
|
|
(const char *) aHeadersData,
|
|
|
|
aHeadersDataLen,
|
|
|
|
PR_FALSE,
|
|
|
|
PR_TRUE); // last arg says we are headers, no /r/n/r/n fixup!
|
|
|
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv),"failed in creating plugin header data stream");
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32 blockPopups =
|
|
|
|
nsContentUtils::GetIntPref("privacy.popups.disable_from_plugins");
|
|
|
|
nsAutoPopupStatePusher popupStatePusher((PopupControlState)blockPopups);
|
|
|
|
|
|
|
|
rv = lh->OnLinkClick(mContent, uri, unitarget.get(),
|
|
|
|
postDataStream, headersDataStream);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const char *aStatusMsg)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
rv = this->ShowStatus(NS_ConvertUTF8toUTF16(aStatusMsg).get());
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::ShowStatus(const PRUnichar *aStatusMsg)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
if (!mOwner) {
|
|
|
|
return rv;
|
|
|
|
}
|
2007-03-30 14:11:41 -07:00
|
|
|
nsCOMPtr<nsISupports> cont = mOwner->PresContext()->GetContainer();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!cont) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(cont, &rv));
|
|
|
|
if (NS_FAILED(rv) || !docShellItem) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
|
|
|
rv = docShellItem->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
|
|
if (NS_FAILED(rv) || !treeOwner) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(treeOwner, &rv));
|
|
|
|
if (NS_FAILED(rv) || !browserChrome) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
|
|
|
|
aStatusMsg);
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetDocument(nsIDocument* *aDocument)
|
|
|
|
{
|
|
|
|
if (!aDocument)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
// XXX sXBL/XBL2 issue: current doc or owner doc?
|
|
|
|
// But keep in mind bug 322414 comment 33
|
|
|
|
NS_IF_ADDREF(*aDocument = mContent->GetOwnerDoc());
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRect(nsPluginRect *invalidRect)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
2007-12-22 00:56:57 -08:00
|
|
|
if (mOwner && invalidRect && mWidgetVisible) {
|
2008-07-13 15:23:04 -07:00
|
|
|
nsPresContext* presContext = mOwner->PresContext();
|
|
|
|
nsRect rect(presContext->DevPixelsToAppUnits(invalidRect->left),
|
|
|
|
presContext->DevPixelsToAppUnits(invalidRect->top),
|
|
|
|
presContext->DevPixelsToAppUnits(invalidRect->right - invalidRect->left),
|
|
|
|
presContext->DevPixelsToAppUnits(invalidRect->bottom - invalidRect->top));
|
|
|
|
mOwner->Invalidate(rect);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::InvalidateRegion(nsPluginRegion invalidRegion)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::ForceRedraw()
|
|
|
|
{
|
2008-04-06 12:02:28 -07:00
|
|
|
NS_ENSURE_TRUE(mOwner,NS_ERROR_NULL_POINTER);
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIView* view = mOwner->GetView();
|
|
|
|
if (view) {
|
|
|
|
return view->GetViewManager()->Composite();
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-06-29 11:53:52 -07:00
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
|
2009-06-29 12:38:09 -07:00
|
|
|
{
|
2009-06-29 11:53:52 -07:00
|
|
|
if (!mOwner) {
|
|
|
|
NS_WARNING("plugin owner has no owner in getting doc's window handle");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2007-07-02 20:41:34 -07:00
|
|
|
#if defined(XP_WIN) || defined(XP_OS2)
|
2009-06-29 11:53:52 -07:00
|
|
|
void** pvalue = (void**)value;
|
|
|
|
nsIViewManager* vm = mOwner->PresContext()->GetPresShell()->GetViewManager();
|
|
|
|
if (!vm)
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-03-22 10:30:00 -07:00
|
|
|
#if defined(XP_WIN)
|
2009-06-29 11:53:52 -07:00
|
|
|
// This property is provided to allow a "windowless" plugin to determine the window it is drawing
|
|
|
|
// in, so it can translate mouse coordinates it receives directly from the operating system
|
|
|
|
// to coordinates relative to itself.
|
|
|
|
|
|
|
|
// The original code (outside this #if) returns the document's window, which is OK if the window the "windowless" plugin
|
|
|
|
// 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
|
|
|
|
|
|
|
|
// To make sure "windowless" plugins always get the right origin for translating mouse coordinates, this code
|
|
|
|
// determines the window handle of the mozilla window containing the "windowless" plugin.
|
|
|
|
|
|
|
|
// Given that this HWND may not be that of the document's window, there is a slight risk
|
|
|
|
// of confusing a plugin that is using this HWND for illicit purposes, but since the documentation
|
|
|
|
// does not suggest this HWND IS that of the document window, rather that of the window
|
|
|
|
// the plugin is drawn in, this seems like a safe fix.
|
|
|
|
|
|
|
|
// we only attempt to get the nearest window if this really is a "windowless" plugin so as not
|
|
|
|
// to change any behaviour for the much more common windowed plugins,
|
|
|
|
// though why this method would even be being called for a windowed plugin escapes me.
|
|
|
|
if (mPluginWindow && mPluginWindow->type == nsPluginWindowType_Drawable) {
|
|
|
|
// it turns out that flash also uses this window for determining focus, and is currently
|
|
|
|
// unable to show a caret correctly if we return the enclosing window. Therefore for
|
|
|
|
// now we only return the enclosing window when there is an actual offset which
|
|
|
|
// would otherwise cause coordinates to be offset incorrectly. (i.e.
|
|
|
|
// if the enclosing window if offset from the document window)
|
|
|
|
//
|
|
|
|
// fixing both the caret and ability to interact issues for a windowless control in a non document aligned windw
|
|
|
|
// does not seem to be possible without a change to the flash plugin
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 11:53:52 -07:00
|
|
|
nsIWidget* win = mOwner->GetWindow();
|
|
|
|
if (win) {
|
|
|
|
nsIView *view = nsIView::GetViewFor(win);
|
|
|
|
NS_ASSERTION(view, "No view for widget");
|
2009-07-21 17:45:09 -07:00
|
|
|
nsPoint offset = view->GetOffsetTo(nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-29 11:53:52 -07:00
|
|
|
if (offset.x || offset.y) {
|
|
|
|
// in the case the two windows are offset from eachother, we do go ahead and return the correct enclosing window
|
|
|
|
// so that mouse co-ordinates are not messed up.
|
|
|
|
*pvalue = (void*)win->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
if (*pvalue)
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2009-06-29 12:38:09 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-07-21 17:45:09 -07:00
|
|
|
// simply return the topmost document window
|
2009-06-29 12:38:09 -07:00
|
|
|
nsCOMPtr<nsIWidget> widget;
|
2009-07-21 17:45:09 -07:00
|
|
|
nsresult rv = vm->GetRootWidget(getter_AddRefs(widget));
|
2009-06-29 12:38:09 -07:00
|
|
|
if (widget) {
|
|
|
|
*pvalue = (void*)widget->GetNativeData(NS_NATIVE_WINDOW);
|
|
|
|
} else {
|
|
|
|
NS_ASSERTION(widget, "couldn't get doc's widget in getting doc's window handle");
|
|
|
|
}
|
2009-06-29 11:53:52 -07:00
|
|
|
|
2009-06-29 12:38:09 -07:00
|
|
|
return rv;
|
2007-07-02 20:41:34 -07:00
|
|
|
#elif defined(MOZ_WIDGET_GTK2)
|
2009-06-29 11:53:52 -07:00
|
|
|
// X11 window managers want the toplevel window for WM_TRANSIENT_FOR.
|
|
|
|
nsIWidget* win = mOwner->GetWindow();
|
|
|
|
if (!win)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
GdkWindow* gdkWindow = static_cast<GdkWindow*>(win->GetNativeData(NS_NATIVE_WINDOW));
|
|
|
|
if (!gdkWindow)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
gdkWindow = gdk_window_get_toplevel(gdkWindow);
|
2008-08-06 13:48:55 -07:00
|
|
|
#ifdef MOZ_X11
|
2009-06-29 11:53:52 -07:00
|
|
|
*static_cast<Window*>(value) = GDK_WINDOW_XID(gdkWindow);
|
2008-08-06 13:48:55 -07:00
|
|
|
#endif
|
2009-06-29 11:53:52 -07:00
|
|
|
return NS_OK;
|
|
|
|
#else
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2007-07-02 20:41:34 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, nsPluginEvent* event)
|
|
|
|
{
|
|
|
|
if (!menu || !event)
|
|
|
|
return NPERR_GENERIC_ERROR;
|
|
|
|
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
if (GetEventModel() != NPEventModelCocoa)
|
|
|
|
return NPERR_INCOMPATIBLE_VERSION_ERROR;
|
|
|
|
|
|
|
|
return NS_NPAPI_ShowCocoaContextMenu(static_cast<void*>(menu), mWidget,
|
|
|
|
static_cast<NPCocoaEvent*>(event->event));
|
|
|
|
#else
|
|
|
|
return NPERR_INCOMPATIBLE_VERSION_ERROR;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
|
|
|
double *destX, double *destY, NPCoordinateSpace destSpace)
|
|
|
|
{
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
if (!mWidget)
|
|
|
|
return PR_FALSE;
|
|
|
|
|
|
|
|
return NS_NPAPI_ConvertPointCocoa(mWidget->GetNativeData(NS_NATIVE_WIDGET),
|
|
|
|
sourceX, sourceY, sourceSpace, destX, destY, destSpace);
|
|
|
|
#else
|
|
|
|
// we should implement this for all platforms
|
|
|
|
return PR_FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
|
|
|
|
*result = nsPluginTagType_Unknown;
|
|
|
|
|
|
|
|
nsIAtom *atom = mContent->Tag();
|
|
|
|
|
|
|
|
if (atom == nsGkAtoms::applet)
|
|
|
|
*result = nsPluginTagType_Applet;
|
|
|
|
else if (atom == nsGkAtoms::embed)
|
|
|
|
*result = nsPluginTagType_Embed;
|
|
|
|
else if (atom == nsGkAtoms::object)
|
|
|
|
*result = nsPluginTagType_Object;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetTagText(const char* *result)
|
|
|
|
{
|
2009-06-15 14:36:11 -07:00
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
if (nsnull == mTagText) {
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mContent, &rv));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
nsCOMPtr<nsIDocument> document;
|
|
|
|
rv = GetDocument(getter_AddRefs(document));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(document);
|
|
|
|
NS_ASSERTION(domDoc, "Need a document");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
nsCOMPtr<nsIDocumentEncoder> docEncoder(do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "text/html", &rv));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
rv = docEncoder->Init(domDoc, NS_LITERAL_STRING("text/html"), nsIDocumentEncoder::OutputEncodeBasicEntities);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
nsCOMPtr<nsIDOMRange> range(do_CreateInstance(kRangeCID,&rv));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
rv = range->SelectNode(node);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
docEncoder->SetRange(range);
|
|
|
|
nsString elementHTML;
|
|
|
|
rv = docEncoder->EncodeToString(elementHTML);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
mTagText = ToNewUTF8String(elementHTML);
|
|
|
|
if (!mTagText)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
*result = mTagText;
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetParameters(PRUint16& n, const char*const*& names, const char*const*& values)
|
|
|
|
{
|
|
|
|
nsresult rv = EnsureCachedAttrParamArrays();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
n = mNumCachedParams;
|
|
|
|
if (n) {
|
|
|
|
names = (const char **)(mCachedAttrParamNames + mNumCachedAttrs + 1);
|
|
|
|
values = (const char **)(mCachedAttrParamValues + mNumCachedAttrs + 1);
|
|
|
|
} else
|
|
|
|
names = values = nsnull;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetParameter(const char* name, const char* *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(name);
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
|
|
|
|
nsresult rv = EnsureCachedAttrParamArrays();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
*result = nsnull;
|
|
|
|
|
|
|
|
for (int i = mNumCachedAttrs + 1; i < (mNumCachedParams + 1 + mNumCachedAttrs); i++) {
|
|
|
|
if (0 == PL_strcasecmp(mCachedAttrParamNames[i], name)) {
|
|
|
|
*result = mCachedAttrParamValues[i];
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetDocumentBase(const char* *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
if (mDocumentBase.IsEmpty()) {
|
|
|
|
if (!mOwner) {
|
|
|
|
*result = nsnull;
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDocument* doc = mContent->GetOwnerDoc();
|
|
|
|
NS_ASSERTION(doc, "Must have an owner doc");
|
|
|
|
rv = doc->GetBaseURI()->GetSpec(mDocumentBase);
|
|
|
|
}
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
*result = ToNewCString(mDocumentBase);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsDataHashtable<nsDepCharHashKey, const char *> * gCharsetMap;
|
|
|
|
typedef struct {
|
|
|
|
char mozName[16];
|
|
|
|
char javaName[12];
|
|
|
|
} moz2javaCharset;
|
|
|
|
|
|
|
|
/* XXX If you add any strings longer than
|
|
|
|
* {"x-mac-cyrillic", "MacCyrillic"},
|
|
|
|
* {"x-mac-ukrainian", "MacUkraine"},
|
|
|
|
* to the following array then you MUST update the
|
|
|
|
* sizes of the arrays in the moz2javaCharset struct
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const moz2javaCharset charsets[] =
|
|
|
|
{
|
|
|
|
{"windows-1252", "Cp1252"},
|
|
|
|
{"IBM850", "Cp850"},
|
|
|
|
{"IBM852", "Cp852"},
|
|
|
|
{"IBM855", "Cp855"},
|
|
|
|
{"IBM857", "Cp857"},
|
|
|
|
{"IBM828", "Cp862"},
|
|
|
|
{"IBM864", "Cp864"},
|
|
|
|
{"IBM866", "Cp866"},
|
|
|
|
{"windows-1250", "Cp1250"},
|
|
|
|
{"windows-1251", "Cp1251"},
|
|
|
|
{"windows-1253", "Cp1253"},
|
|
|
|
{"windows-1254", "Cp1254"},
|
|
|
|
{"windows-1255", "Cp1255"},
|
|
|
|
{"windows-1256", "Cp1256"},
|
|
|
|
{"windows-1257", "Cp1257"},
|
|
|
|
{"windows-1258", "Cp1258"},
|
|
|
|
{"EUC-JP", "EUC_JP"},
|
|
|
|
{"EUC-KR", "EUC_KR"},
|
|
|
|
{"x-euc-tw", "EUC_TW"},
|
|
|
|
{"gb18030", "GB18030"},
|
|
|
|
{"x-gbk", "GBK"},
|
|
|
|
{"ISO-2022-JP", "ISO2022JP"},
|
|
|
|
{"ISO-2022-KR", "ISO2022KR"},
|
|
|
|
{"ISO-8859-2", "ISO8859_2"},
|
|
|
|
{"ISO-8859-3", "ISO8859_3"},
|
|
|
|
{"ISO-8859-4", "ISO8859_4"},
|
|
|
|
{"ISO-8859-5", "ISO8859_5"},
|
|
|
|
{"ISO-8859-6", "ISO8859_6"},
|
|
|
|
{"ISO-8859-7", "ISO8859_7"},
|
|
|
|
{"ISO-8859-8", "ISO8859_8"},
|
|
|
|
{"ISO-8859-9", "ISO8859_9"},
|
|
|
|
{"ISO-8859-13", "ISO8859_13"},
|
|
|
|
{"x-johab", "Johab"},
|
|
|
|
{"KOI8-R", "KOI8_R"},
|
|
|
|
{"TIS-620", "MS874"},
|
|
|
|
{"windows-936", "MS936"},
|
|
|
|
{"x-windows-949", "MS949"},
|
|
|
|
{"x-mac-arabic", "MacArabic"},
|
|
|
|
{"x-mac-croatian", "MacCroatia"},
|
|
|
|
{"x-mac-cyrillic", "MacCyrillic"},
|
|
|
|
{"x-mac-greek", "MacGreek"},
|
|
|
|
{"x-mac-hebrew", "MacHebrew"},
|
|
|
|
{"x-mac-icelandic", "MacIceland"},
|
|
|
|
{"x-mac-roman", "MacRoman"},
|
|
|
|
{"x-mac-romanian", "MacRomania"},
|
|
|
|
{"x-mac-ukrainian", "MacUkraine"},
|
|
|
|
{"Shift_JIS", "SJIS"},
|
|
|
|
{"TIS-620", "TIS620"}
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetDocumentEncoding(const char* *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
*result = nsnull;
|
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
// XXX sXBL/XBL2 issue: current doc or owner doc?
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
rv = GetDocument(getter_AddRefs(doc));
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get document");
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
const nsCString &charset = doc->GetDocumentCharacterSet();
|
|
|
|
|
|
|
|
if (charset.IsEmpty())
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// common charsets and those not requiring conversion first
|
|
|
|
if (charset.EqualsLiteral("us-ascii")) {
|
|
|
|
*result = PL_strdup("US_ASCII");
|
|
|
|
} else if (charset.EqualsLiteral("ISO-8859-1") ||
|
|
|
|
!nsCRT::strncmp(PromiseFlatCString(charset).get(), "UTF", 3)) {
|
|
|
|
*result = ToNewCString(charset);
|
|
|
|
} else {
|
|
|
|
if (!gCharsetMap) {
|
|
|
|
const int NUM_CHARSETS = sizeof(charsets) / sizeof(moz2javaCharset);
|
|
|
|
gCharsetMap = new nsDataHashtable<nsDepCharHashKey, const char*>();
|
|
|
|
if (!gCharsetMap || !gCharsetMap->Init(NUM_CHARSETS))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
for (PRUint16 i = 0; i < NUM_CHARSETS; i++) {
|
|
|
|
gCharsetMap->Put(charsets[i].mozName, charsets[i].javaName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if found mapping, return it; otherwise return original charset
|
|
|
|
const char *mapping;
|
|
|
|
*result = gCharsetMap->Get(charset.get(), &mapping) ? PL_strdup(mapping) :
|
|
|
|
ToNewCString(charset);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (*result) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetAlignment(const char* *result)
|
|
|
|
{
|
|
|
|
return GetAttribute("ALIGN", result);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetWidth(PRUint32 *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
|
|
|
|
NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
|
|
|
|
|
|
|
|
*result = mPluginWindow->width;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetHeight(PRUint32 *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
|
|
|
|
NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
|
|
|
|
|
|
|
|
*result = mPluginWindow->height;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetBorderVertSpace(PRUint32 *result)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
const char *vspace;
|
|
|
|
|
|
|
|
rv = GetAttribute("VSPACE", &vspace);
|
|
|
|
|
|
|
|
if (NS_OK == rv) {
|
|
|
|
if (*result != 0)
|
|
|
|
*result = (PRUint32)atol(vspace);
|
|
|
|
else
|
|
|
|
*result = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*result = 0;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetBorderHorizSpace(PRUint32 *result)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
const char *hspace;
|
|
|
|
|
|
|
|
rv = GetAttribute("HSPACE", &hspace);
|
|
|
|
|
|
|
|
if (NS_OK == rv) {
|
|
|
|
if (*result != 0)
|
|
|
|
*result = (PRUint32)atol(hspace);
|
|
|
|
else
|
|
|
|
*result = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
*result = 0;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::GetUniqueID(PRUint32 *result)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(result);
|
|
|
|
*result = NS_PTR_TO_INT32(mOwner);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cache the attributes and/or parameters of our tag into a single set
|
|
|
|
// of arrays to be compatible with 4.x. The attributes go first,
|
|
|
|
// followed by a PARAM/null and then any PARAM tags. Also, hold the
|
|
|
|
// cached array around for the duration of the life of the instance
|
|
|
|
// because 4.x did. See bug 111008.
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::EnsureCachedAttrParamArrays()
|
|
|
|
{
|
|
|
|
if (mCachedAttrParamValues)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_PRECONDITION(((mNumCachedAttrs + mNumCachedParams) == 0) &&
|
|
|
|
!mCachedAttrParamNames,
|
|
|
|
"re-cache of attrs/params not implemented! use the DOM "
|
|
|
|
"node directy instead");
|
|
|
|
NS_ENSURE_TRUE(mOwner, NS_ERROR_NULL_POINTER);
|
|
|
|
|
|
|
|
// first, we need to find out how much we need to allocate for our
|
|
|
|
// arrays count up attributes
|
|
|
|
mNumCachedAttrs = 0;
|
|
|
|
|
|
|
|
PRUint32 cattrs = mContent->GetAttrCount();
|
|
|
|
|
|
|
|
if (cattrs < 0x0000FFFF) {
|
|
|
|
// unsigned 32 bits to unsigned 16 bits conversion
|
2007-07-08 00:08:04 -07:00
|
|
|
mNumCachedAttrs = static_cast<PRUint16>(cattrs);
|
2007-03-22 10:30:00 -07:00
|
|
|
} else {
|
|
|
|
mNumCachedAttrs = 0xFFFE; // minus one in case we add an extra "src" entry below
|
|
|
|
}
|
|
|
|
|
|
|
|
// now, we need to find all the PARAM tags that are children of us
|
|
|
|
// however, be carefull NOT to include any PARAMs that don't have us
|
|
|
|
// as a direct parent. For nested object (or applet) tags, be sure
|
|
|
|
// to only round up the param tags that coorespond with THIS
|
|
|
|
// instance. And also, weed out any bogus tags that may get in the
|
|
|
|
// way, see bug 39609. Then, with any param tag that meet our
|
|
|
|
// qualification, temporarly cache them in an nsCOMArray until
|
|
|
|
// we can figure out what size to make our fixed char* array.
|
|
|
|
|
|
|
|
mNumCachedParams = 0;
|
|
|
|
nsCOMArray<nsIDOMElement> ourParams;
|
|
|
|
|
|
|
|
// use the DOM to get us ALL our dependent PARAM tags, even if not
|
|
|
|
// ours
|
|
|
|
nsCOMPtr<nsIDOMElement> mydomElement = do_QueryInterface(mContent);
|
|
|
|
NS_ENSURE_TRUE(mydomElement, NS_ERROR_NO_INTERFACE);
|
|
|
|
|
2009-06-19 09:15:23 -07:00
|
|
|
nsCOMPtr<nsIDOMNodeList> allParams;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Making DOM method calls can cause our frame to go away, which
|
|
|
|
// might kill us...
|
|
|
|
nsCOMPtr<nsIPluginInstanceOwner> kungFuDeathGrip(this);
|
|
|
|
|
2009-06-09 00:41:19 -07:00
|
|
|
NS_NAMED_LITERAL_STRING(xhtml_ns, "http://www.w3.org/1999/xhtml");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-06-09 00:41:19 -07:00
|
|
|
mydomElement->GetElementsByTagNameNS(xhtml_ns, NS_LITERAL_STRING("param"),
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(allParams));
|
|
|
|
|
|
|
|
if (allParams) {
|
|
|
|
PRUint32 numAllParams;
|
|
|
|
allParams->GetLength(&numAllParams);
|
|
|
|
// loop through every so called dependent PARAM tag to check if it
|
|
|
|
// "belongs" to us
|
|
|
|
|
|
|
|
for (PRUint32 i = 0; i < numAllParams; i++) {
|
|
|
|
nsCOMPtr<nsIDOMNode> pnode;
|
|
|
|
allParams->Item(i, getter_AddRefs(pnode));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(pnode);
|
|
|
|
if (domelement) {
|
|
|
|
// let's NOT count up param tags that don't have a name attribute
|
|
|
|
nsAutoString name;
|
|
|
|
domelement->GetAttribute(NS_LITERAL_STRING("name"), name);
|
|
|
|
if (!name.IsEmpty()) {
|
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
|
|
nsCOMPtr<nsIDOMHTMLObjectElement> domobject;
|
|
|
|
nsCOMPtr<nsIDOMHTMLAppletElement> domapplet;
|
|
|
|
pnode->GetParentNode(getter_AddRefs(parent));
|
|
|
|
// walk up the parents of this PARAM until we find an object
|
|
|
|
// (or applet) tag
|
|
|
|
|
|
|
|
while (!(domobject || domapplet) && parent) {
|
|
|
|
domobject = do_QueryInterface(parent);
|
|
|
|
domapplet = do_QueryInterface(parent);
|
|
|
|
nsCOMPtr<nsIDOMNode> temp;
|
|
|
|
parent->GetParentNode(getter_AddRefs(temp));
|
|
|
|
parent = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (domapplet || domobject) {
|
|
|
|
if (domapplet)
|
|
|
|
parent = domapplet;
|
|
|
|
else
|
|
|
|
parent = domobject;
|
|
|
|
|
|
|
|
// now check to see if this PARAM's parent is us. if so,
|
|
|
|
// cache it for later
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> mydomNode = do_QueryInterface(mydomElement);
|
|
|
|
if (parent == mydomNode) {
|
|
|
|
ourParams.AppendObject(domelement);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We're done with DOM method calls now; make sure we still have a frame.
|
|
|
|
NS_ENSURE_TRUE(mOwner, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
PRUint32 cparams = ourParams.Count(); // unsigned 32 bits to unsigned 16 bits conversion
|
|
|
|
if (cparams < 0x0000FFFF)
|
2007-07-08 00:08:04 -07:00
|
|
|
mNumCachedParams = static_cast<PRUint16>(cparams);
|
2007-03-22 10:30:00 -07:00
|
|
|
else
|
|
|
|
mNumCachedParams = 0xFFFF;
|
|
|
|
|
|
|
|
// Some plugins were never written to understand the "data" attribute of the OBJECT tag.
|
|
|
|
// Real and WMP will not play unless they find a "src" attribute, see bug 152334.
|
|
|
|
// Nav 4.x would simply replace the "data" with "src". Because some plugins correctly
|
|
|
|
// look for "data", lets instead copy the "data" attribute and add another entry
|
|
|
|
// to the bottom of the array if there isn't already a "src" specified.
|
|
|
|
PRInt16 numRealAttrs = mNumCachedAttrs;
|
|
|
|
nsAutoString data;
|
|
|
|
if (mContent->Tag() == nsGkAtoms::object
|
|
|
|
&& !mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::src)
|
|
|
|
&& mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, data)) {
|
|
|
|
mNumCachedAttrs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// now lets make the arrays
|
|
|
|
mCachedAttrParamNames = (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs + 1 + mNumCachedParams), 1);
|
|
|
|
NS_ENSURE_TRUE(mCachedAttrParamNames, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
mCachedAttrParamValues = (char **)PR_Calloc(sizeof(char *) * (mNumCachedAttrs + 1 + mNumCachedParams), 1);
|
|
|
|
NS_ENSURE_TRUE(mCachedAttrParamValues, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
// let's fill in our attributes
|
|
|
|
PRInt16 c = 0;
|
|
|
|
|
|
|
|
// Some plugins (eg Flash, see bug 234675.) are actually sensitive to the
|
|
|
|
// attribute order. So we want to make sure we give the plugin the
|
|
|
|
// attributes in the order they came in in the source, to be compatible with
|
|
|
|
// other browsers. Now in HTML, the storage order is the reverse of the
|
|
|
|
// source order, while in XML and XHTML it's the same as the source order
|
|
|
|
// (see the AddAttributes functions in the HTML and XML content sinks).
|
|
|
|
PRInt16 start, end, increment;
|
2009-08-24 17:51:57 -07:00
|
|
|
if (mContent->IsNodeOfType(nsINode::eHTML) &&
|
2009-06-09 00:41:19 -07:00
|
|
|
mContent->IsInHTMLDocument()) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// HTML. Walk attributes in reverse order.
|
|
|
|
start = numRealAttrs - 1;
|
|
|
|
end = -1;
|
|
|
|
increment = -1;
|
|
|
|
} else {
|
|
|
|
// XHTML or XML. Walk attributes in forward order.
|
|
|
|
start = 0;
|
|
|
|
end = numRealAttrs;
|
|
|
|
increment = 1;
|
|
|
|
}
|
|
|
|
for (PRInt16 index = start; index != end; index += increment) {
|
|
|
|
const nsAttrName* attrName = mContent->GetAttrNameAt(index);
|
|
|
|
nsIAtom* atom = attrName->LocalName();
|
|
|
|
nsAutoString value;
|
|
|
|
mContent->GetAttr(attrName->NamespaceID(), atom, value);
|
|
|
|
nsAutoString name;
|
|
|
|
atom->ToString(name);
|
|
|
|
|
|
|
|
FixUpURLS(name, value);
|
|
|
|
|
|
|
|
mCachedAttrParamNames [c] = ToNewUTF8String(name);
|
|
|
|
mCachedAttrParamValues[c] = ToNewUTF8String(value);
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the conditions above were met, copy the "data" attribute to a "src" array entry
|
|
|
|
if (data.Length()) {
|
|
|
|
mCachedAttrParamNames [mNumCachedAttrs-1] = ToNewUTF8String(NS_LITERAL_STRING("SRC"));
|
|
|
|
mCachedAttrParamValues[mNumCachedAttrs-1] = ToNewUTF8String(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
// add our PARAM and null separator
|
|
|
|
mCachedAttrParamNames [mNumCachedAttrs] = ToNewUTF8String(NS_LITERAL_STRING("PARAM"));
|
|
|
|
mCachedAttrParamValues[mNumCachedAttrs] = nsnull;
|
|
|
|
|
|
|
|
// now fill in the PARAM name/value pairs from the cached DOM nodes
|
|
|
|
c = 0;
|
|
|
|
for (PRInt16 idx = 0; idx < mNumCachedParams; idx++) {
|
|
|
|
nsIDOMElement* param = ourParams.ObjectAt(idx);
|
|
|
|
if (param) {
|
|
|
|
nsAutoString name;
|
|
|
|
nsAutoString value;
|
|
|
|
param->GetAttribute(NS_LITERAL_STRING("name"), name); // check for empty done above
|
|
|
|
param->GetAttribute(NS_LITERAL_STRING("value"), value);
|
|
|
|
|
|
|
|
FixUpURLS(name, value);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* According to the HTML 4.01 spec, at
|
|
|
|
* http://www.w3.org/TR/html4/types.html#type-cdata
|
|
|
|
* ''User agents may ignore leading and trailing
|
|
|
|
* white space in CDATA attribute values (e.g., "
|
|
|
|
* myval " may be interpreted as "myval"). Authors
|
|
|
|
* should not declare attribute values with
|
|
|
|
* leading or trailing white space.''
|
|
|
|
* However, do not trim consecutive spaces as in bug 122119
|
|
|
|
*/
|
|
|
|
name.Trim(" \n\r\t\b", PR_TRUE, PR_TRUE, PR_FALSE);
|
|
|
|
value.Trim(" \n\r\t\b", PR_TRUE, PR_TRUE, PR_FALSE);
|
|
|
|
mCachedAttrParamNames [mNumCachedAttrs + 1 + c] = ToNewUTF8String(name);
|
|
|
|
mCachedAttrParamValues[mNumCachedAttrs + 1 + c] = ToNewUTF8String(value);
|
|
|
|
c++; // rules!
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Here's where we forward events to plugins.
|
|
|
|
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
|
2009-08-04 18:36:37 -07:00
|
|
|
static void InitializeEventRecord(EventRecord* event, Point* aMousePosition)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-08-25 23:53:00 -07:00
|
|
|
memset(event, 0, sizeof(EventRecord));
|
2009-08-04 18:36:37 -07:00
|
|
|
if (aMousePosition) {
|
|
|
|
event->where = *aMousePosition;
|
|
|
|
} else {
|
|
|
|
::GetGlobalMouse(&event->where);
|
|
|
|
}
|
2008-08-25 23:53:00 -07:00
|
|
|
event->when = ::TickCount();
|
|
|
|
event->modifiers = ::GetCurrentEventKeyModifiers();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
static void InitializeNPCocoaEvent(NPCocoaEvent* event)
|
|
|
|
{
|
|
|
|
memset(event, 0, sizeof(NPCocoaEvent));
|
|
|
|
}
|
|
|
|
|
2007-03-26 18:07:57 -07:00
|
|
|
NPDrawingModel nsPluginInstanceOwner::GetDrawingModel()
|
|
|
|
{
|
|
|
|
#ifndef NP_NO_QUICKDRAW
|
|
|
|
NPDrawingModel drawingModel = NPDrawingModelQuickDraw;
|
|
|
|
#else
|
|
|
|
NPDrawingModel drawingModel = NPDrawingModelCoreGraphics;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!mInstance)
|
|
|
|
return drawingModel;
|
|
|
|
|
|
|
|
mInstance->GetValue(nsPluginInstanceVariable_DrawingModel,
|
|
|
|
(void *)&drawingModel);
|
|
|
|
|
|
|
|
return drawingModel;
|
|
|
|
}
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
NPEventModel nsPluginInstanceOwner::GetEventModel()
|
|
|
|
{
|
|
|
|
#ifndef NP_NO_QUICKDRAW
|
|
|
|
NPEventModel eventModel = NPEventModelCarbon;
|
|
|
|
#else
|
|
|
|
NPEventModel eventModel = NPEventModelCocoa;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!mInstance)
|
|
|
|
return eventModel;
|
|
|
|
|
|
|
|
mInstance->GetValue(nsPluginInstanceVariable_EventModel,
|
|
|
|
(void *)&eventModel);
|
|
|
|
|
|
|
|
return eventModel;
|
|
|
|
}
|
|
|
|
|
2008-10-30 10:40:53 -07:00
|
|
|
// Currently (on OS X in Cocoa widgets) any changes made as a result of
|
|
|
|
// calling GetPluginPort() are immediately reflected in the nsPluginWindow
|
|
|
|
// structure that has been passed to the plugin via SetWindow(). This is
|
|
|
|
// because calls to nsChildView::GetNativeData(NS_NATIVE_PLUGIN_PORT_CG)
|
|
|
|
// always return a pointer to the same internal (private) object, but may
|
|
|
|
// make changes inside that object. All calls to GetPluginPort() made while
|
|
|
|
// the plugin is active (i.e. excluding those made at our initialization)
|
|
|
|
// need to take this into account. The easiest way to do so is to replace
|
|
|
|
// them with calls to SetPluginPortAndDetectChange(). This method keeps track
|
|
|
|
// of when calls to GetPluginPort() result in changes, and sets a flag to make
|
|
|
|
// sure SetWindow() gets called the next time through FixUpPluginWindow(), so
|
|
|
|
// that the plugin is notified of these changes.
|
|
|
|
nsPluginPort* nsPluginInstanceOwner::SetPluginPortAndDetectChange()
|
|
|
|
{
|
|
|
|
if (!mPluginWindow)
|
|
|
|
return nsnull;
|
|
|
|
nsPluginPort* pluginPort = GetPluginPort();
|
|
|
|
if (!pluginPort)
|
|
|
|
return nsnull;
|
|
|
|
mPluginWindow->window = pluginPort;
|
|
|
|
|
|
|
|
NPDrawingModel drawingModel = GetDrawingModel();
|
|
|
|
|
|
|
|
#ifndef NP_NO_QUICKDRAW
|
|
|
|
if (drawingModel == NPDrawingModelQuickDraw) {
|
|
|
|
if (mPluginWindow->window->qdPort.port != mPluginPortCopy.qdPort.port) {
|
|
|
|
mPluginPortCopy.qdPort.port = mPluginWindow->window->qdPort.port;
|
|
|
|
mPluginPortChanged = PR_TRUE;
|
|
|
|
}
|
|
|
|
} else if (drawingModel == NPDrawingModelCoreGraphics)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if ((mPluginWindow->window->cgPort.context != mPluginPortCopy.cgPort.context) ||
|
|
|
|
(mPluginWindow->window->cgPort.window != mPluginPortCopy.cgPort.window)) {
|
|
|
|
mPluginPortCopy.cgPort.context = mPluginWindow->window->cgPort.context;
|
|
|
|
mPluginPortCopy.cgPort.window = mPluginWindow->window->cgPort.window;
|
|
|
|
mPluginPortChanged = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return mPluginWindow->window;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsPluginInstanceOwner::BeginCGPaint()
|
|
|
|
{
|
|
|
|
++mInCGPaintLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsPluginInstanceOwner::EndCGPaint()
|
|
|
|
{
|
|
|
|
--mInCGPaintLevel;
|
2009-08-26 17:29:47 -07:00
|
|
|
NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!");
|
2008-10-30 10:40:53 -07:00
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-02-02 17:23:48 -08:00
|
|
|
// static
|
|
|
|
PRUint32
|
|
|
|
nsPluginInstanceOwner::GetEventloopNestingLevel()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
|
|
|
PRUint32 currentLevel = 0;
|
|
|
|
if (appShell) {
|
|
|
|
appShell->GetEventloopNestingLevel(¤tLevel);
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
// Cocoa widget code doesn't process UI events through the normal
|
|
|
|
// appshell event loop, so it needs an additional count here.
|
|
|
|
currentLevel++;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// No idea how this happens... but Linux doesn't consistently
|
|
|
|
// process UI events through the appshell event loop. If we get a 0
|
|
|
|
// here on any platform we increment the level just in case so that
|
|
|
|
// we make sure we always tear the plugin down eventually.
|
|
|
|
if (!currentLevel) {
|
|
|
|
currentLevel++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return currentLevel;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
|
|
|
|
{
|
|
|
|
#ifdef XP_MACOSX
|
2009-08-26 17:29:47 -07:00
|
|
|
if (GetEventModel() != NPEventModelCarbon)
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
CancelTimer();
|
|
|
|
|
|
|
|
if (mInstance) {
|
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
|
|
|
|
EventRecord scrollEvent;
|
2009-08-04 18:36:37 -07:00
|
|
|
InitializeEventRecord(&scrollEvent, nsnull);
|
2009-07-10 17:20:32 -07:00
|
|
|
scrollEvent.what = NPEventType_ScrollingBeginsEvent;
|
2009-06-15 14:36:11 -07:00
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
void* window = FixUpPluginWindow(ePluginPaintDisable);
|
2009-06-15 14:36:11 -07:00
|
|
|
if (window) {
|
|
|
|
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(window) };
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
}
|
|
|
|
pluginWidget->EndDrawPlugin();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-15 14:36:11 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-06-15 14:36:11 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
|
|
|
|
{
|
|
|
|
#ifdef XP_MACOSX
|
2009-08-26 17:29:47 -07:00
|
|
|
if (GetEventModel() != NPEventModelCarbon)
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
if (mInstance) {
|
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
|
|
|
|
EventRecord scrollEvent;
|
2009-08-04 18:36:37 -07:00
|
|
|
InitializeEventRecord(&scrollEvent, nsnull);
|
2009-07-10 17:20:32 -07:00
|
|
|
scrollEvent.what = NPEventType_ScrollingEndsEvent;
|
2009-06-15 14:36:11 -07:00
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
void* window = FixUpPluginWindow(ePluginPaintEnable);
|
2009-06-15 14:36:11 -07:00
|
|
|
if (window) {
|
|
|
|
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(window) };
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-15 14:36:11 -07:00
|
|
|
pluginWidget->EndDrawPlugin();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-15 14:36:11 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
StartTimer(NORMAL_PLUGIN_DELAY);
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*=============== nsIFocusListener ======================*/
|
|
|
|
nsresult nsPluginInstanceOwner::Focus(nsIDOMEvent * aFocusEvent)
|
|
|
|
{
|
|
|
|
mContentFocused = PR_TRUE;
|
|
|
|
return DispatchFocusToPlugin(aFocusEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::Blur(nsIDOMEvent * aFocusEvent)
|
|
|
|
{
|
|
|
|
mContentFocused = PR_FALSE;
|
|
|
|
return DispatchFocusToPlugin(aFocusEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
|
|
|
|
{
|
|
|
|
#ifndef XP_MACOSX
|
|
|
|
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type) {
|
|
|
|
// continue only for cases without child window
|
|
|
|
return aFocusEvent->PreventDefault(); // consume event
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aFocusEvent));
|
|
|
|
if (privateEvent) {
|
2008-10-09 16:23:07 -07:00
|
|
|
nsEvent * theEvent = privateEvent->GetInternalNSEvent();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (theEvent) {
|
|
|
|
// we only care about the message in ProcessEvent
|
|
|
|
nsGUIEvent focusEvent(NS_IS_TRUSTED_EVENT(theEvent), theEvent->message,
|
|
|
|
nsnull);
|
|
|
|
nsEventStatus rv = ProcessEvent(focusEvent);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == rv) {
|
|
|
|
aFocusEvent->PreventDefault();
|
|
|
|
aFocusEvent->StopPropagation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, focusEvent null");
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchFocusToPlugin failed, privateEvent null");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*=============== nsIKeyListener ======================*/
|
|
|
|
nsresult nsPluginInstanceOwner::KeyDown(nsIDOMEvent* aKeyEvent)
|
|
|
|
{
|
|
|
|
return DispatchKeyToPlugin(aKeyEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::KeyUp(nsIDOMEvent* aKeyEvent)
|
|
|
|
{
|
|
|
|
return DispatchKeyToPlugin(aKeyEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
|
|
|
|
{
|
2009-08-26 17:29:47 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
// send KeyPress events only for Mac OS X Carbon event model
|
|
|
|
if (GetEventModel() != NPEventModelCarbon)
|
|
|
|
return aKeyEvent->PreventDefault();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// KeyPress events are really synthesized keyDown events.
|
|
|
|
// Here we check the native message of the event so that
|
|
|
|
// we won't send the plugin two keyDown events.
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aKeyEvent));
|
|
|
|
if (privateEvent) {
|
2008-10-09 16:23:07 -07:00
|
|
|
nsEvent *theEvent = privateEvent->GetInternalNSEvent();
|
2007-03-22 10:30:00 -07:00
|
|
|
const nsGUIEvent *guiEvent = (nsGUIEvent*)theEvent;
|
|
|
|
const EventRecord *ev = (EventRecord*)(guiEvent->nativeMsg);
|
|
|
|
if (guiEvent &&
|
|
|
|
guiEvent->message == NS_KEY_PRESS &&
|
|
|
|
ev &&
|
|
|
|
ev->what == keyDown)
|
|
|
|
return aKeyEvent->PreventDefault(); // consume event
|
|
|
|
}
|
|
|
|
|
|
|
|
// Nasty hack to avoid recursive event dispatching with Java. Java can
|
|
|
|
// dispatch key events to a TSM handler, which comes back and calls
|
|
|
|
// [ChildView insertText:] on the cocoa widget, which sends a key
|
|
|
|
// event back down.
|
|
|
|
static PRBool sInKeyDispatch = PR_FALSE;
|
|
|
|
|
|
|
|
if (sInKeyDispatch)
|
|
|
|
return aKeyEvent->PreventDefault(); // consume event
|
|
|
|
|
|
|
|
sInKeyDispatch = PR_TRUE;
|
|
|
|
nsresult rv = DispatchKeyToPlugin(aKeyEvent);
|
|
|
|
sInKeyDispatch = PR_FALSE;
|
|
|
|
return rv;
|
|
|
|
#else
|
2008-12-14 19:54:54 -08:00
|
|
|
|
|
|
|
if (SendNativeEvents())
|
2009-02-19 23:42:29 -08:00
|
|
|
DispatchKeyToPlugin(aKeyEvent);
|
2008-12-14 19:54:54 -08:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mInstance) {
|
|
|
|
// If this event is going to the plugin, we want to kill it.
|
|
|
|
// Not actually sending keypress to the plugin, since we didn't before.
|
|
|
|
aKeyEvent->PreventDefault();
|
|
|
|
aKeyEvent->StopPropagation();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::DispatchKeyToPlugin(nsIDOMEvent* aKeyEvent)
|
|
|
|
{
|
2009-02-25 07:25:12 -08:00
|
|
|
#if !defined(XP_MACOSX) && !defined(MOZ_COMPOSITED_PLUGINS)
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
|
|
|
|
return aKeyEvent->PreventDefault(); // consume event
|
|
|
|
// continue only for cases without child window
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (mInstance) {
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aKeyEvent));
|
|
|
|
if (privateEvent) {
|
2008-10-09 16:23:07 -07:00
|
|
|
nsKeyEvent *keyEvent = (nsKeyEvent *) privateEvent->GetInternalNSEvent();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (keyEvent) {
|
|
|
|
nsEventStatus rv = ProcessEvent(*keyEvent);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == rv) {
|
|
|
|
aKeyEvent->PreventDefault();
|
|
|
|
aKeyEvent->StopPropagation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, keyEvent null");
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchKeyToPlugin failed, privateEvent null");
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-08-25 22:36:17 -07:00
|
|
|
/*=============== nsIDOMMouseMotionListener ======================*/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::MouseMove(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
#if !defined(XP_MACOSX)
|
|
|
|
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
|
|
|
|
return aMouseEvent->PreventDefault(); // consume event
|
|
|
|
// continue only for cases without child window
|
|
|
|
#endif
|
|
|
|
|
2008-08-25 23:53:00 -07:00
|
|
|
// don't send mouse events if we are hidden
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mWidgetVisible)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aMouseEvent));
|
|
|
|
if (privateEvent) {
|
2008-10-09 16:23:07 -07:00
|
|
|
nsMouseEvent* mouseEvent = (nsMouseEvent *) privateEvent->GetInternalNSEvent();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mouseEvent) {
|
|
|
|
nsEventStatus rv = ProcessEvent(*mouseEvent);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == rv) {
|
|
|
|
return aMouseEvent->PreventDefault(); // consume event
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::MouseMove failed, mouseEvent null");
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::MouseMove failed, privateEvent null");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-08-25 17:02:26 -07:00
|
|
|
/*=============== nsIDOMMouseListener ======================*/
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::MouseDown(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
2009-02-25 07:25:12 -08:00
|
|
|
#if !defined(XP_MACOSX) && !defined(MOZ_COMPOSITED_PLUGINS)
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
|
|
|
|
return aMouseEvent->PreventDefault(); // consume event
|
|
|
|
// continue only for cases without child window
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// if the plugin is windowless, we need to set focus ourselves
|
|
|
|
// otherwise, we might not get key events
|
|
|
|
if (mOwner && mPluginWindow &&
|
|
|
|
mPluginWindow->type == nsPluginWindowType_Drawable) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (fm) {
|
|
|
|
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mContent);
|
|
|
|
fm->SetFocus(elem, 0);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aMouseEvent));
|
|
|
|
if (privateEvent) {
|
2008-10-09 16:23:07 -07:00
|
|
|
nsMouseEvent* mouseEvent = (nsMouseEvent *) privateEvent->GetInternalNSEvent();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mouseEvent) {
|
|
|
|
nsEventStatus rv = ProcessEvent(*mouseEvent);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == rv) {
|
|
|
|
return aMouseEvent->PreventDefault(); // consume event
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::MouseDown failed, mouseEvent null");
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::MouseDown failed, privateEvent null");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::MouseUp(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
return DispatchMouseToPlugin(aMouseEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::MouseClick(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
return DispatchMouseToPlugin(aMouseEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::MouseDblClick(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
return DispatchMouseToPlugin(aMouseEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::MouseOver(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
return DispatchMouseToPlugin(aMouseEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::MouseOut(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
|
|
|
return DispatchMouseToPlugin(aMouseEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent)
|
|
|
|
{
|
2009-02-25 07:25:12 -08:00
|
|
|
#if !defined(XP_MACOSX) && !defined(MOZ_COMPOSITED_PLUGINS)
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mPluginWindow || nsPluginWindowType_Window == mPluginWindow->type)
|
|
|
|
return aMouseEvent->PreventDefault(); // consume event
|
|
|
|
// continue only for cases without child window
|
|
|
|
#endif
|
2008-08-25 23:53:00 -07:00
|
|
|
// don't send mouse events if we are hidden
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!mWidgetVisible)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aMouseEvent));
|
|
|
|
if (privateEvent) {
|
2008-10-09 16:23:07 -07:00
|
|
|
nsMouseEvent* mouseEvent = (nsMouseEvent *) privateEvent->GetInternalNSEvent();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mouseEvent) {
|
|
|
|
nsEventStatus rv = ProcessEvent(*mouseEvent);
|
|
|
|
if (nsEventStatus_eConsumeNoDefault == rv) {
|
|
|
|
aMouseEvent->PreventDefault();
|
|
|
|
aMouseEvent->StopPropagation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, mouseEvent null");
|
|
|
|
}
|
|
|
|
else NS_ASSERTION(PR_FALSE, "nsPluginInstanceOwner::DispatchMouseToPlugin failed, privateEvent null");
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
|
|
|
|
{
|
2008-10-17 13:04:55 -07:00
|
|
|
if (mInstance) {
|
2009-08-27 08:51:46 -07:00
|
|
|
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aEvent));
|
|
|
|
nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent));
|
|
|
|
if (privateEvent && dragEvent) {
|
|
|
|
nsEvent* ievent = privateEvent->GetInternalNSEvent();
|
|
|
|
if (ievent && NS_IS_TRUSTED_EVENT(ievent) &&
|
|
|
|
(ievent->message == NS_DRAGDROP_ENTER || ievent->message == NS_DRAGDROP_OVER)) {
|
|
|
|
// set the allowed effect to none here. The plugin should set it if necessary
|
|
|
|
nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
|
|
|
|
dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
|
|
|
|
if (dataTransfer)
|
|
|
|
dataTransfer->SetEffectAllowed(NS_LITERAL_STRING("none"));
|
|
|
|
}
|
|
|
|
|
2008-10-17 13:04:55 -07:00
|
|
|
// Let the plugin handle drag events.
|
|
|
|
aEvent->PreventDefault();
|
|
|
|
aEvent->StopPropagation();
|
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-07-02 20:39:44 -07:00
|
|
|
#ifdef MOZ_X11
|
|
|
|
static unsigned int XInputEventState(const nsInputEvent& anEvent)
|
|
|
|
{
|
|
|
|
unsigned int state = 0;
|
2008-08-25 23:53:00 -07:00
|
|
|
if (anEvent.isShift) state |= ShiftMask;
|
|
|
|
if (anEvent.isControl) state |= ControlMask;
|
|
|
|
if (anEvent.isAlt) state |= Mod1Mask;
|
|
|
|
if (anEvent.isMeta) state |= Mod4Mask;
|
2007-07-02 20:39:44 -07:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2009-02-25 07:25:12 -08:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
2009-05-14 19:26:10 -07:00
|
|
|
static void find_dest_id(XID top, XID *root, XID *dest, int target_x, int target_y)
|
2009-02-25 07:25:12 -08:00
|
|
|
{
|
|
|
|
XID target_id = top;
|
|
|
|
XID parent;
|
|
|
|
XID *children;
|
|
|
|
unsigned int nchildren;
|
|
|
|
while (1) {
|
|
|
|
loop:
|
|
|
|
//printf("searching %x\n", target_id);
|
2009-08-12 02:49:54 -07:00
|
|
|
if (!XQueryTree(GDK_DISPLAY(), target_id, root, &parent, &children, &nchildren) ||
|
|
|
|
!nchildren)
|
2009-02-25 07:25:12 -08:00
|
|
|
break;
|
2009-08-12 02:49:54 -07:00
|
|
|
for (unsigned int i=0; i<nchildren; i++) {
|
|
|
|
Window root;
|
|
|
|
int x, y;
|
|
|
|
unsigned int width, height;
|
|
|
|
unsigned int border_width, depth;
|
|
|
|
XGetGeometry(GDK_DISPLAY(), children[i], &root, &x, &y,
|
|
|
|
&width, &height, &border_width,
|
|
|
|
&depth);
|
|
|
|
//printf("target: %d %d\n", target_x, target_y);
|
|
|
|
//printf("geom: %dx%x @ %dx%d\n", width, height, x, y);
|
|
|
|
// XXX: we may need to be more careful here, i.e. if
|
|
|
|
// this condition matches more than one child
|
|
|
|
if (target_x >= x && target_y >= y &&
|
|
|
|
target_x <= x + int(width) &&
|
|
|
|
target_y <= y + int(height)) {
|
|
|
|
target_id = children[i];
|
|
|
|
// printf("found new target: %x\n", target_id);
|
|
|
|
XFree(children);
|
|
|
|
goto loop;
|
|
|
|
}
|
2009-02-25 07:25:12 -08:00
|
|
|
}
|
2009-08-12 02:49:54 -07:00
|
|
|
XFree(children);
|
|
|
|
/* no children contain the target */
|
|
|
|
break;
|
2009-02-25 07:25:12 -08:00
|
|
|
}
|
|
|
|
*dest = target_id;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
nsEventStatus nsPluginInstanceOwner::ProcessEventX11Composited(const nsGUIEvent& anEvent)
|
|
|
|
{
|
|
|
|
//printf("nsGUIEvent.message: %d\n", anEvent.message);
|
|
|
|
nsEventStatus rv = nsEventStatus_eIgnore;
|
|
|
|
if (!mInstance || !mOwner) // if mInstance is null, we shouldn't be here
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// this code supports windowless plugins
|
|
|
|
nsIWidget* widget = anEvent.widget;
|
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
pluginEvent.event.type = 0;
|
|
|
|
|
|
|
|
switch(anEvent.eventStructType)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_EVENT:
|
|
|
|
{
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_CLICK:
|
|
|
|
case NS_MOUSE_DOUBLECLICK:
|
|
|
|
// Button up/down events sent instead.
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get reference point relative to plugin origin.
|
|
|
|
const nsPresContext* presContext = mOwner->PresContext();
|
|
|
|
nsPoint appPoint =
|
|
|
|
nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mOwner);
|
|
|
|
nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
|
|
|
|
presContext->AppUnitsToDevPixels(appPoint.y));
|
|
|
|
mLastPoint = pluginPoint;
|
|
|
|
const nsMouseEvent& mouseEvent =
|
|
|
|
static_cast<const nsMouseEvent&>(anEvent);
|
|
|
|
// Get reference point relative to screen:
|
|
|
|
nsIntPoint rootPoint(-1,-1);
|
|
|
|
if (widget)
|
|
|
|
rootPoint = anEvent.refPoint + widget->WidgetToScreenOffset();
|
|
|
|
#ifdef MOZ_WIDGET_GTK2
|
|
|
|
Window root = GDK_ROOT_WINDOW();
|
|
|
|
#else
|
|
|
|
Window root = None; // Could XQueryTree, but this is not important.
|
|
|
|
#endif
|
|
|
|
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_ENTER_SYNTH:
|
|
|
|
case NS_MOUSE_EXIT_SYNTH:
|
|
|
|
{
|
|
|
|
XCrossingEvent& event = pluginEvent.event.xcrossing;
|
|
|
|
event.type = anEvent.message == NS_MOUSE_ENTER_SYNTH ?
|
|
|
|
EnterNotify : LeaveNotify;
|
|
|
|
event.root = root;
|
|
|
|
event.time = anEvent.time;
|
|
|
|
event.x = pluginPoint.x;
|
|
|
|
event.y = pluginPoint.y;
|
|
|
|
event.x_root = rootPoint.x;
|
|
|
|
event.y_root = rootPoint.y;
|
|
|
|
event.state = XInputEventState(mouseEvent);
|
|
|
|
// information lost
|
|
|
|
event.subwindow = None;
|
|
|
|
event.mode = -1;
|
|
|
|
event.detail = NotifyDetailNone;
|
|
|
|
event.same_screen = True;
|
|
|
|
event.focus = mContentFocused;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
{
|
|
|
|
XMotionEvent& event = pluginEvent.event.xmotion;
|
|
|
|
event.type = MotionNotify;
|
|
|
|
event.root = root;
|
|
|
|
event.time = anEvent.time;
|
|
|
|
event.x = pluginPoint.x;
|
|
|
|
event.y = pluginPoint.y;
|
|
|
|
event.x_root = rootPoint.x;
|
|
|
|
event.y_root = rootPoint.y;
|
|
|
|
event.state = XInputEventState(mouseEvent);
|
|
|
|
// information lost
|
|
|
|
event.subwindow = None;
|
|
|
|
event.is_hint = NotifyNormal;
|
|
|
|
event.same_screen = True;
|
|
|
|
XEvent be;
|
|
|
|
be.xmotion = pluginEvent.event.xmotion;
|
|
|
|
//printf("xmotion: %d %d\n", be.xmotion.x, be.xmotion.y);
|
|
|
|
XID w = (XID)mPluginWindow->window;
|
|
|
|
be.xmotion.window = w;
|
|
|
|
XSendEvent (be.xmotion.display, w,
|
|
|
|
FALSE, ButtonMotionMask, &be);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
|
|
|
{
|
|
|
|
XButtonEvent& event = pluginEvent.event.xbutton;
|
|
|
|
event.type = anEvent.message == NS_MOUSE_BUTTON_DOWN ?
|
|
|
|
ButtonPress : ButtonRelease;
|
|
|
|
event.root = root;
|
|
|
|
event.time = anEvent.time;
|
|
|
|
event.x = pluginPoint.x;
|
|
|
|
event.y = pluginPoint.y;
|
|
|
|
event.x_root = rootPoint.x;
|
|
|
|
event.y_root = rootPoint.y;
|
|
|
|
event.state = XInputEventState(mouseEvent);
|
|
|
|
switch (mouseEvent.button)
|
|
|
|
{
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
event.button = 2;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
event.button = 3;
|
|
|
|
break;
|
|
|
|
default: // nsMouseEvent::eLeftButton;
|
|
|
|
event.button = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// information lost:
|
|
|
|
event.subwindow = None;
|
|
|
|
event.same_screen = True;
|
|
|
|
XEvent be;
|
|
|
|
be.xbutton = event;
|
|
|
|
XID target;
|
|
|
|
XID root;
|
|
|
|
int wx, wy;
|
|
|
|
unsigned int width, height, border_width, depth;
|
|
|
|
|
|
|
|
//printf("xbutton: %d %d %d\n", anEvent.message, be.xbutton.x, be.xbutton.y);
|
|
|
|
XID w = (XID)mPluginWindow->window;
|
|
|
|
XGetGeometry(GDK_DISPLAY(), w, &root, &wx, &wy, &width, &height, &border_width, &depth);
|
|
|
|
find_dest_id(w, &root, &target, pluginPoint.x + wx, pluginPoint.y + wy);
|
|
|
|
be.xbutton.window = target;
|
|
|
|
XSendEvent (GDK_DISPLAY(), target,
|
|
|
|
FALSE, event.type == ButtonPress ? ButtonPressMask : ButtonReleaseMask, &be);
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
//XXX case NS_MOUSE_SCROLL_EVENT: not received.
|
|
|
|
|
|
|
|
case NS_KEY_EVENT:
|
|
|
|
if (anEvent.nativeMsg)
|
|
|
|
{
|
|
|
|
XKeyEvent &event = pluginEvent.event.xkey;
|
|
|
|
#ifdef MOZ_WIDGET_GTK2
|
|
|
|
event.root = GDK_ROOT_WINDOW();
|
|
|
|
event.time = anEvent.time;
|
|
|
|
const GdkEventKey* gdkEvent =
|
|
|
|
static_cast<const GdkEventKey*>(anEvent.nativeMsg);
|
|
|
|
event.keycode = gdkEvent->hardware_keycode;
|
|
|
|
event.state = gdkEvent->state;
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_KEY_DOWN:
|
|
|
|
event.type = XKeyPress;
|
|
|
|
break;
|
|
|
|
case NS_KEY_UP:
|
|
|
|
event.type = KeyRelease;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// Information that could be obtained from nativeMsg but we may not
|
|
|
|
// want to promise to provide:
|
|
|
|
event.subwindow = None;
|
|
|
|
event.x = 0;
|
|
|
|
event.y = 0;
|
|
|
|
event.x_root = -1;
|
|
|
|
event.y_root = -1;
|
|
|
|
event.same_screen = False;
|
|
|
|
XEvent be;
|
|
|
|
be.xkey = event;
|
|
|
|
XID target;
|
|
|
|
XID root;
|
|
|
|
int wx, wy;
|
|
|
|
unsigned int width, height, border_width, depth;
|
|
|
|
|
|
|
|
//printf("xkey: %d %d %d\n", anEvent.message, be.xkey.keycode, be.xkey.state);
|
|
|
|
XID w = (XID)mPluginWindow->window;
|
|
|
|
XGetGeometry(GDK_DISPLAY(), w, &root, &wx, &wy, &width, &height, &border_width, &depth);
|
|
|
|
find_dest_id(w, &root, &target, mLastPoint.x + wx, mLastPoint.y + wy);
|
|
|
|
be.xkey.window = target;
|
|
|
|
XSendEvent (GDK_DISPLAY(), target,
|
|
|
|
FALSE, event.type == XKeyPress ? KeyPressMask : KeyReleaseMask, &be);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If we need to send synthesized key events, then
|
|
|
|
// DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
|
|
|
|
// gdk_keymap_get_entries_for_keyval will be useful, but the
|
|
|
|
// mappings will not be unique.
|
|
|
|
NS_WARNING("Synthesized key event not sent to plugin");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_FOCUS_CONTENT:
|
|
|
|
case NS_BLUR_CONTENT:
|
|
|
|
{
|
|
|
|
XFocusChangeEvent &event = pluginEvent.event.xfocus;
|
|
|
|
event.type =
|
|
|
|
anEvent.message == NS_FOCUS_CONTENT ? FocusIn : FocusOut;
|
|
|
|
// information lost:
|
|
|
|
event.mode = -1;
|
|
|
|
event.detail = NotifyDetailNone;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pluginEvent.event.type) {
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("Unhandled event message %d with struct type %d\n",
|
|
|
|
anEvent.message, anEvent.eventStructType));
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in (useless) generic event information.
|
|
|
|
XAnyEvent& event = pluginEvent.event.xany;
|
|
|
|
event.display = widget ?
|
|
|
|
static_cast<Display*>(widget->GetNativeData(NS_NATIVE_DISPLAY)) : nsnull;
|
|
|
|
event.window = None; // not a real window
|
|
|
|
// information lost:
|
|
|
|
event.serial = 0;
|
|
|
|
event.send_event = False;
|
|
|
|
|
2009-08-12 02:49:54 -07:00
|
|
|
#if 0
|
2009-02-25 07:25:12 -08:00
|
|
|
/* we've sent the event via XSendEvent so don't send it directly to the plugin */
|
2009-08-12 02:49:54 -07:00
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
2009-02-25 07:25:12 -08:00
|
|
|
if (eventHandled)
|
2009-08-12 02:49:54 -07:00
|
|
|
rv = nsEventStatus_eConsumeNoDefault;
|
|
|
|
#endif
|
2009-02-25 07:25:12 -08:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
|
|
|
|
{
|
|
|
|
// printf("nsGUIEvent.message: %d\n", anEvent.message);
|
2009-02-25 07:25:12 -08:00
|
|
|
|
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
if (mPluginWindow && mPluginWindow->type != nsPluginWindowType_Drawable)
|
|
|
|
return ProcessEventX11Composited(anEvent);
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsEventStatus rv = nsEventStatus_eIgnore;
|
2009-08-26 17:29:47 -07:00
|
|
|
|
2007-07-02 20:39:44 -07:00
|
|
|
if (!mInstance || !mOwner) // if mInstance is null, we shouldn't be here
|
2009-08-26 17:29:47 -07:00
|
|
|
return nsEventStatus_eIgnore;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
if (mWidget) {
|
2009-08-26 17:29:47 -07:00
|
|
|
// we never care about synthesized mouse enter
|
|
|
|
if (anEvent.message == NS_MOUSE_ENTER_SYNTH)
|
|
|
|
return nsEventStatus_eIgnore;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
|
2009-08-26 17:29:47 -07:00
|
|
|
NPEventModel eventModel = GetEventModel();
|
|
|
|
|
|
|
|
// If we have to synthesize an event we'll use one of these.
|
|
|
|
EventRecord synthCarbonEvent;
|
|
|
|
NPCocoaEvent synthCocoaEvent;
|
|
|
|
|
2009-07-10 17:20:32 -07:00
|
|
|
void* event = anEvent.nativeMsg;
|
2009-08-26 17:29:47 -07:00
|
|
|
|
|
|
|
if (!event) {
|
2009-08-04 18:36:37 -07:00
|
|
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mOwner);
|
|
|
|
nsPresContext* presContext = mOwner->PresContext();
|
|
|
|
nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
|
|
|
|
presContext->AppUnitsToDevPixels(pt.y));
|
2009-08-26 17:29:47 -07:00
|
|
|
|
|
|
|
if (eventModel == NPEventModelCarbon) {
|
|
|
|
Point carbonPt = { ptPx.y + mPluginWindow->y, ptPx.x + mPluginWindow->x };
|
|
|
|
|
|
|
|
event = &synthCarbonEvent;
|
|
|
|
InitializeEventRecord(&synthCarbonEvent, &carbonPt);
|
|
|
|
} else {
|
|
|
|
event = &synthCocoaEvent;
|
|
|
|
InitializeNPCocoaEvent(&synthCocoaEvent);
|
|
|
|
}
|
2009-08-04 18:36:37 -07:00
|
|
|
|
|
|
|
switch (anEvent.message) {
|
|
|
|
case NS_FOCUS_CONTENT:
|
|
|
|
case NS_BLUR_CONTENT:
|
2009-08-26 17:29:47 -07:00
|
|
|
if (eventModel == NPEventModelCarbon) {
|
|
|
|
synthCarbonEvent.what = (anEvent.message == NS_FOCUS_CONTENT) ?
|
2009-08-04 18:36:37 -07:00
|
|
|
NPEventType_GetFocusEvent : NPEventType_LoseFocusEvent;
|
2009-08-26 17:29:47 -07:00
|
|
|
} else {
|
|
|
|
synthCocoaEvent.type = NPCocoaEventFocusChanged;
|
|
|
|
synthCocoaEvent.data.focus.hasFocus = (anEvent.message == NS_FOCUS_CONTENT);
|
|
|
|
}
|
2009-08-04 18:36:37 -07:00
|
|
|
break;
|
|
|
|
case NS_MOUSE_MOVE:
|
2009-08-26 17:29:47 -07:00
|
|
|
if (eventModel == NPEventModelCarbon) {
|
|
|
|
synthCarbonEvent.what = osEvt;
|
|
|
|
} else {
|
|
|
|
synthCocoaEvent.type = NPCocoaEventMouseMoved;
|
|
|
|
synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
|
|
|
|
synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
|
|
|
|
}
|
2009-08-04 18:36:37 -07:00
|
|
|
break;
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
2009-08-26 17:29:47 -07:00
|
|
|
if (eventModel == NPEventModelCarbon) {
|
|
|
|
synthCarbonEvent.what = mouseDown;
|
|
|
|
} else {
|
|
|
|
synthCocoaEvent.type = NPCocoaEventMouseDown;
|
|
|
|
synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
|
|
|
|
synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
|
|
|
|
}
|
2009-08-04 18:36:37 -07:00
|
|
|
break;
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
2009-08-26 17:29:47 -07:00
|
|
|
if (eventModel == NPEventModelCarbon) {
|
|
|
|
synthCarbonEvent.what = mouseUp;
|
|
|
|
} else {
|
|
|
|
synthCocoaEvent.type = NPCocoaEventMouseUp;
|
|
|
|
synthCocoaEvent.data.mouse.pluginX = static_cast<double>(ptPx.x);
|
|
|
|
synthCocoaEvent.data.mouse.pluginY = static_cast<double>(ptPx.y);
|
|
|
|
}
|
2009-08-04 18:36:37 -07:00
|
|
|
break;
|
2009-07-10 17:20:32 -07:00
|
|
|
}
|
2009-08-26 17:29:47 -07:00
|
|
|
} else if ((eventModel == NPEventModelCarbon) && (static_cast<EventRecord*>(event)->what == nullEvent)) {
|
|
|
|
Point carbonPt = { 20000, 20000 };
|
|
|
|
InitializeEventRecord(&synthCarbonEvent, &carbonPt);
|
|
|
|
event = &synthCarbonEvent;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
// Work around an issue in the Flash plugin, which can cache a pointer
|
|
|
|
// to a doomed TSM document (one that belongs to a NSTSMInputContext)
|
|
|
|
// and try to activate it after it has been deleted. See bug 183313.
|
|
|
|
if (eventModel == NPEventModelCarbon && anEvent.message == NS_FOCUS_CONTENT)
|
2007-03-22 10:30:00 -07:00
|
|
|
::DeactivateTSMDocument(::TSMGetActiveDocument());
|
|
|
|
|
2007-03-26 18:07:57 -07:00
|
|
|
PRBool eventHandled = PR_FALSE;
|
2009-08-26 17:29:47 -07:00
|
|
|
void* window = FixUpPluginWindow(ePluginPaintEnable);
|
|
|
|
if (window || (eventModel == NPEventModelCocoa)) {
|
|
|
|
nsPluginEvent pluginEvent = { event, nsPluginPlatformWindowRef(window) };
|
2007-03-22 10:30:00 -07:00
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eventHandled && !(anEvent.eventStructType == NS_MOUSE_EVENT &&
|
|
|
|
anEvent.message == NS_MOUSE_BUTTON_DOWN &&
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<const nsMouseEvent&>(anEvent).button ==
|
2007-03-22 10:30:00 -07:00
|
|
|
nsMouseEvent::eLeftButton &&
|
|
|
|
!mContentFocused))
|
|
|
|
rv = nsEventStatus_eConsumeNoDefault;
|
|
|
|
|
|
|
|
pluginWidget->EndDrawPlugin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef XP_WIN
|
|
|
|
// this code supports windowless plugins
|
|
|
|
nsPluginEvent * pPluginEvent = (nsPluginEvent *)anEvent.nativeMsg;
|
|
|
|
// we can get synthetic events from the nsEventStateManager... these
|
|
|
|
// have no nativeMsg
|
|
|
|
nsPluginEvent pluginEvent;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
if (anEvent.eventStructType == NS_MOUSE_EVENT) {
|
2009-08-04 18:36:37 -07:00
|
|
|
if (!pPluginEvent) {
|
|
|
|
// XXX Should extend this list to synthesize events for more event
|
|
|
|
// types
|
|
|
|
pluginEvent.event = 0;
|
|
|
|
const nsMouseEvent* mouseEvent = static_cast<const nsMouseEvent*>(&anEvent);
|
|
|
|
switch (anEvent.message) {
|
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
pluginEvent.event = WM_MOUSEMOVE;
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_BUTTON_DOWN: {
|
|
|
|
static const int downMsgs[] =
|
|
|
|
{ WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
|
|
|
|
pluginEvent.event = downMsgs[mouseEvent->button];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NS_MOUSE_BUTTON_UP: {
|
|
|
|
static const int upMsgs[] =
|
|
|
|
{ WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
|
|
|
|
pluginEvent.event = upMsgs[mouseEvent->button];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case NS_MOUSE_DOUBLECLICK: {
|
|
|
|
static const int dblClickMsgs[] =
|
|
|
|
{ WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK };
|
|
|
|
pluginEvent.event = dblClickMsgs[mouseEvent->button];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pluginEvent.event) {
|
|
|
|
pPluginEvent = &pluginEvent;
|
|
|
|
pluginEvent.wParam =
|
|
|
|
(::GetKeyState(VK_CONTROL) ? MK_CONTROL : 0) |
|
|
|
|
(::GetKeyState(VK_SHIFT) ? MK_SHIFT : 0) |
|
|
|
|
(::GetKeyState(VK_LBUTTON) ? MK_LBUTTON : 0) |
|
|
|
|
(::GetKeyState(VK_MBUTTON) ? MK_MBUTTON : 0) |
|
|
|
|
(::GetKeyState(VK_RBUTTON) ? MK_RBUTTON : 0) |
|
|
|
|
(::GetKeyState(VK_XBUTTON1) ? MK_XBUTTON1 : 0) |
|
|
|
|
(::GetKeyState(VK_XBUTTON2) ? MK_XBUTTON2 : 0);
|
|
|
|
}
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
if (pPluginEvent) {
|
|
|
|
// Make event coordinates relative to our enclosing widget,
|
|
|
|
// not the widget they were received on.
|
|
|
|
// See use of nsPluginEvent in widget/src/windows/nsWindow.cpp
|
|
|
|
// for why this assert should be safe
|
|
|
|
NS_ASSERTION(anEvent.message == NS_MOUSE_BUTTON_DOWN ||
|
|
|
|
anEvent.message == NS_MOUSE_BUTTON_UP ||
|
|
|
|
anEvent.message == NS_MOUSE_DOUBLECLICK ||
|
|
|
|
anEvent.message == NS_MOUSE_ENTER_SYNTH ||
|
|
|
|
anEvent.message == NS_MOUSE_EXIT_SYNTH ||
|
|
|
|
anEvent.message == NS_MOUSE_MOVE,
|
|
|
|
"Incorrect event type for coordinate translation");
|
|
|
|
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mOwner);
|
|
|
|
nsPresContext* presContext = mOwner->PresContext();
|
|
|
|
nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
|
|
|
|
presContext->AppUnitsToDevPixels(pt.y));
|
|
|
|
nsIntPoint widgetPtPx = ptPx + mOwner->GetWindowOriginInPixels(PR_TRUE);
|
|
|
|
pPluginEvent->lParam = MAKELPARAM(widgetPtPx.x, widgetPtPx.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!pPluginEvent) {
|
|
|
|
switch (anEvent.message) {
|
|
|
|
case NS_FOCUS_CONTENT:
|
|
|
|
pluginEvent.event = WM_SETFOCUS;
|
|
|
|
pluginEvent.wParam = 0;
|
|
|
|
pluginEvent.lParam = 0;
|
|
|
|
pPluginEvent = &pluginEvent;
|
|
|
|
break;
|
|
|
|
case NS_BLUR_CONTENT:
|
|
|
|
pluginEvent.event = WM_KILLFOCUS;
|
|
|
|
pluginEvent.wParam = 0;
|
|
|
|
pluginEvent.lParam = 0;
|
|
|
|
pPluginEvent = &pluginEvent;
|
|
|
|
break;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pPluginEvent) {
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(pPluginEvent, &eventHandled);
|
|
|
|
if (eventHandled)
|
|
|
|
rv = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-07-02 20:39:44 -07:00
|
|
|
#ifdef MOZ_X11
|
|
|
|
// this code supports windowless plugins
|
|
|
|
nsIWidget* widget = anEvent.widget;
|
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
pluginEvent.event.type = 0;
|
|
|
|
|
|
|
|
switch(anEvent.eventStructType)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_EVENT:
|
|
|
|
{
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_CLICK:
|
|
|
|
case NS_MOUSE_DOUBLECLICK:
|
|
|
|
// Button up/down events sent instead.
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get reference point relative to plugin origin.
|
|
|
|
const nsPresContext* presContext = mOwner->PresContext();
|
|
|
|
nsPoint appPoint =
|
|
|
|
nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mOwner);
|
|
|
|
nsIntPoint pluginPoint(presContext->AppUnitsToDevPixels(appPoint.x),
|
|
|
|
presContext->AppUnitsToDevPixels(appPoint.y));
|
|
|
|
const nsMouseEvent& mouseEvent =
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<const nsMouseEvent&>(anEvent);
|
2007-07-02 20:39:44 -07:00
|
|
|
// Get reference point relative to screen:
|
2009-02-18 16:11:49 -08:00
|
|
|
nsIntPoint rootPoint(-1,-1);
|
2007-07-02 20:39:44 -07:00
|
|
|
if (widget)
|
2009-02-18 16:11:49 -08:00
|
|
|
rootPoint = anEvent.refPoint + widget->WidgetToScreenOffset();
|
2007-07-02 20:39:44 -07:00
|
|
|
#ifdef MOZ_WIDGET_GTK2
|
|
|
|
Window root = GDK_ROOT_WINDOW();
|
|
|
|
#else
|
|
|
|
Window root = None; // Could XQueryTree, but this is not important.
|
|
|
|
#endif
|
|
|
|
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_MOUSE_ENTER_SYNTH:
|
|
|
|
case NS_MOUSE_EXIT_SYNTH:
|
|
|
|
{
|
|
|
|
XCrossingEvent& event = pluginEvent.event.xcrossing;
|
|
|
|
event.type = anEvent.message == NS_MOUSE_ENTER_SYNTH ?
|
|
|
|
EnterNotify : LeaveNotify;
|
|
|
|
event.root = root;
|
|
|
|
event.time = anEvent.time;
|
|
|
|
event.x = pluginPoint.x;
|
|
|
|
event.y = pluginPoint.y;
|
|
|
|
event.x_root = rootPoint.x;
|
|
|
|
event.y_root = rootPoint.y;
|
|
|
|
event.state = XInputEventState(mouseEvent);
|
|
|
|
// information lost
|
|
|
|
event.subwindow = None;
|
|
|
|
event.mode = -1;
|
|
|
|
event.detail = NotifyDetailNone;
|
|
|
|
event.same_screen = True;
|
|
|
|
event.focus = mContentFocused;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_MOVE:
|
|
|
|
{
|
|
|
|
XMotionEvent& event = pluginEvent.event.xmotion;
|
|
|
|
event.type = MotionNotify;
|
|
|
|
event.root = root;
|
|
|
|
event.time = anEvent.time;
|
|
|
|
event.x = pluginPoint.x;
|
|
|
|
event.y = pluginPoint.y;
|
|
|
|
event.x_root = rootPoint.x;
|
|
|
|
event.y_root = rootPoint.y;
|
|
|
|
event.state = XInputEventState(mouseEvent);
|
|
|
|
// information lost
|
|
|
|
event.subwindow = None;
|
|
|
|
event.is_hint = NotifyNormal;
|
|
|
|
event.same_screen = True;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_MOUSE_BUTTON_DOWN:
|
|
|
|
case NS_MOUSE_BUTTON_UP:
|
|
|
|
{
|
|
|
|
XButtonEvent& event = pluginEvent.event.xbutton;
|
|
|
|
event.type = anEvent.message == NS_MOUSE_BUTTON_DOWN ?
|
|
|
|
ButtonPress : ButtonRelease;
|
|
|
|
event.root = root;
|
|
|
|
event.time = anEvent.time;
|
|
|
|
event.x = pluginPoint.x;
|
|
|
|
event.y = pluginPoint.y;
|
|
|
|
event.x_root = rootPoint.x;
|
|
|
|
event.y_root = rootPoint.y;
|
|
|
|
event.state = XInputEventState(mouseEvent);
|
|
|
|
switch (mouseEvent.button)
|
|
|
|
{
|
|
|
|
case nsMouseEvent::eMiddleButton:
|
|
|
|
event.button = 2;
|
|
|
|
break;
|
|
|
|
case nsMouseEvent::eRightButton:
|
|
|
|
event.button = 3;
|
|
|
|
break;
|
|
|
|
default: // nsMouseEvent::eLeftButton;
|
|
|
|
event.button = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// information lost:
|
|
|
|
event.subwindow = None;
|
|
|
|
event.same_screen = True;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
//XXX case NS_MOUSE_SCROLL_EVENT: not received.
|
|
|
|
|
|
|
|
case NS_KEY_EVENT:
|
|
|
|
if (anEvent.nativeMsg)
|
|
|
|
{
|
|
|
|
XKeyEvent &event = pluginEvent.event.xkey;
|
|
|
|
#ifdef MOZ_WIDGET_GTK2
|
|
|
|
event.root = GDK_ROOT_WINDOW();
|
|
|
|
event.time = anEvent.time;
|
|
|
|
const GdkEventKey* gdkEvent =
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<const GdkEventKey*>(anEvent.nativeMsg);
|
2007-07-02 20:39:44 -07:00
|
|
|
event.keycode = gdkEvent->hardware_keycode;
|
|
|
|
event.state = gdkEvent->state;
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_KEY_DOWN:
|
|
|
|
event.type = XKeyPress;
|
|
|
|
break;
|
|
|
|
case NS_KEY_UP:
|
|
|
|
event.type = KeyRelease;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// Information that could be obtained from nativeMsg but we may not
|
|
|
|
// want to promise to provide:
|
|
|
|
event.subwindow = None;
|
|
|
|
event.x = 0;
|
|
|
|
event.y = 0;
|
|
|
|
event.x_root = -1;
|
|
|
|
event.y_root = -1;
|
|
|
|
event.same_screen = False;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If we need to send synthesized key events, then
|
|
|
|
// DOMKeyCodeToGdkKeyCode(keyEvent.keyCode) and
|
|
|
|
// gdk_keymap_get_entries_for_keyval will be useful, but the
|
|
|
|
// mappings will not be unique.
|
|
|
|
NS_WARNING("Synthesized key event not sent to plugin");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
switch (anEvent.message)
|
|
|
|
{
|
|
|
|
case NS_FOCUS_CONTENT:
|
|
|
|
case NS_BLUR_CONTENT:
|
|
|
|
{
|
|
|
|
XFocusChangeEvent &event = pluginEvent.event.xfocus;
|
|
|
|
event.type =
|
|
|
|
anEvent.message == NS_FOCUS_CONTENT ? FocusIn : FocusOut;
|
|
|
|
// information lost:
|
|
|
|
event.mode = -1;
|
|
|
|
event.detail = NotifyDetailNone;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pluginEvent.event.type) {
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("Unhandled event message %d with struct type %d\n",
|
|
|
|
anEvent.message, anEvent.eventStructType));
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill in (useless) generic event information.
|
|
|
|
XAnyEvent& event = pluginEvent.event.xany;
|
|
|
|
event.display = widget ?
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<Display*>(widget->GetNativeData(NS_NATIVE_DISPLAY)) : nsnull;
|
2007-07-02 20:39:44 -07:00
|
|
|
event.window = None; // not a real window
|
|
|
|
// information lost:
|
|
|
|
event.serial = 0;
|
|
|
|
event.send_event = False;
|
|
|
|
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
if (eventHandled)
|
|
|
|
rv = nsEventStatus_eConsumeNoDefault;
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::Destroy()
|
|
|
|
{
|
|
|
|
// stop the timer explicitly to reduce reference count.
|
|
|
|
CancelTimer();
|
|
|
|
|
|
|
|
// unregister context menu listener
|
|
|
|
if (mCXMenuListener) {
|
|
|
|
mCXMenuListener->Destroy(mContent);
|
2008-02-28 18:06:00 -08:00
|
|
|
mCXMenuListener = nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-05-14 02:11:38 -07:00
|
|
|
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mContent));
|
|
|
|
if (target) {
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventListener> listener;
|
|
|
|
QueryInterface(NS_GET_IID(nsIDOMEventListener), getter_AddRefs(listener));
|
|
|
|
|
|
|
|
// Unregister focus event listener
|
2007-05-14 02:11:38 -07:00
|
|
|
mContent->RemoveEventListenerByIID(listener, NS_GET_IID(nsIDOMFocusListener));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Unregister mouse event listener
|
2007-05-14 02:11:38 -07:00
|
|
|
mContent->RemoveEventListenerByIID(listener, NS_GET_IID(nsIDOMMouseListener));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// now for the mouse motion listener
|
2007-05-14 02:11:38 -07:00
|
|
|
mContent->RemoveEventListenerByIID(listener, NS_GET_IID(nsIDOMMouseMotionListener));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Unregister key event listener;
|
2007-05-14 02:11:38 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("keypress"), listener, PR_TRUE);
|
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("keydown"), listener, PR_TRUE);
|
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("keyup"), listener, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Unregister drag event listener;
|
2008-10-17 13:04:55 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("drop"), listener, PR_TRUE);
|
2007-05-14 02:11:38 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("dragdrop"), listener, PR_TRUE);
|
2008-10-17 13:04:55 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("drag"), listener, PR_TRUE);
|
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("dragenter"), listener, PR_TRUE);
|
2007-05-14 02:11:38 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("dragover"), listener, PR_TRUE);
|
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("dragexit"), listener, PR_TRUE);
|
2008-10-17 13:04:55 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("dragleave"), listener, PR_TRUE);
|
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("dragstart"), listener, PR_TRUE);
|
2007-05-14 02:11:38 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("draggesture"), listener, PR_TRUE);
|
2008-10-17 13:04:55 -07:00
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("dragend"), listener, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-04-23 15:56:40 -07:00
|
|
|
if (mWidget) {
|
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (pluginWidget)
|
|
|
|
pluginWidget->SetPluginInstanceOwner(nsnull);
|
|
|
|
|
|
|
|
if (mDestroyWidget)
|
|
|
|
mWidget->Destroy();
|
2007-08-13 13:47:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare to stop
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
nsPluginInstanceOwner::PrepareToStop(PRBool aDelayedStop)
|
|
|
|
{
|
2009-05-14 19:16:27 -07:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_X11)
|
2007-11-09 14:26:04 -08:00
|
|
|
if (aDelayedStop && mWidget) {
|
2007-08-13 13:47:04 -07:00
|
|
|
// To delay stopping a plugin we need to reparent the plugin
|
|
|
|
// so that we can safely tear down the
|
|
|
|
// plugin after its frame (and view) is gone.
|
|
|
|
|
|
|
|
// Also hide and disable the widget to avoid it from appearing in
|
|
|
|
// odd places after reparenting it, but before it gets destroyed.
|
|
|
|
mWidget->Show(PR_FALSE);
|
|
|
|
mWidget->Enable(PR_FALSE);
|
|
|
|
|
|
|
|
// Reparent the plugins native window. This relies on the widget
|
|
|
|
// and plugin et al not holding any other references to its
|
|
|
|
// parent.
|
|
|
|
mWidget->SetParent(nsnull);
|
|
|
|
|
|
|
|
mDestroyWidget = PR_TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Unregister scroll position listener
|
|
|
|
nsIFrame* parentWithView = mOwner->GetAncestorWithView();
|
|
|
|
nsIView* curView = parentWithView ? parentWithView->GetView() : nsnull;
|
|
|
|
while (curView) {
|
|
|
|
nsIScrollableView* scrollingView = curView->ToScrollableView();
|
|
|
|
if (scrollingView)
|
|
|
|
scrollingView->RemoveScrollPositionListener((nsIScrollPositionListener *)this);
|
|
|
|
|
|
|
|
curView = curView->GetParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Paints are handled differently, so we just simulate an update event.
|
|
|
|
|
2007-07-02 20:33:13 -07:00
|
|
|
#ifdef XP_MACOSX
|
2009-08-26 17:29:47 -07:00
|
|
|
void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (!mInstance || !mOwner)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
|
2009-08-26 17:29:47 -07:00
|
|
|
void* window = FixUpPluginWindow(ePluginPaintEnable);
|
|
|
|
if (GetEventModel() == NPEventModelCarbon && window) {
|
2007-03-22 10:30:00 -07:00
|
|
|
EventRecord updateEvent;
|
2009-08-04 18:36:37 -07:00
|
|
|
InitializeEventRecord(&updateEvent, nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
updateEvent.what = updateEvt;
|
2007-03-26 18:07:57 -07:00
|
|
|
updateEvent.message = UInt32(window);
|
2009-08-26 17:29:47 -07:00
|
|
|
|
|
|
|
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(window) };
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// The context given here is only valid during the HandleEvent call.
|
|
|
|
NPCocoaEvent updateEvent;
|
|
|
|
InitializeNPCocoaEvent(&updateEvent);
|
|
|
|
updateEvent.type = NPCocoaEventDrawRect;
|
|
|
|
updateEvent.data.draw.context = mPluginPortCopy.cgPort.context;
|
|
|
|
updateEvent.data.draw.x = aDirtyRect.X();
|
|
|
|
updateEvent.data.draw.y = aDirtyRect.Y();
|
|
|
|
updateEvent.data.draw.width = aDirtyRect.Width();
|
|
|
|
updateEvent.data.draw.height = aDirtyRect.Height();
|
|
|
|
|
2007-03-26 18:07:57 -07:00
|
|
|
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(window) };
|
2007-03-22 10:30:00 -07:00
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
}
|
|
|
|
pluginWidget->EndDrawPlugin();
|
|
|
|
}
|
2007-07-02 20:33:13 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef XP_WIN
|
2008-10-29 22:28:25 -07:00
|
|
|
void nsPluginInstanceOwner::Paint(const RECT& aDirty, HDC aDC)
|
2007-07-02 20:33:13 -07:00
|
|
|
{
|
|
|
|
if (!mInstance || !mOwner)
|
|
|
|
return;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
pluginEvent.event = WM_PAINT;
|
2008-10-29 22:28:25 -07:00
|
|
|
pluginEvent.wParam = WPARAM(aDC);
|
|
|
|
pluginEvent.lParam = LPARAM(&aDirty);
|
2007-03-22 10:30:00 -07:00
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
2007-07-02 20:33:13 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2007-07-02 20:33:13 -07:00
|
|
|
|
2008-03-10 17:10:55 -07:00
|
|
|
#ifdef XP_OS2
|
|
|
|
void nsPluginInstanceOwner::Paint(const nsRect& aDirtyRect, HPS aHPS)
|
|
|
|
{
|
|
|
|
if (!mInstance || !mOwner)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsPluginWindow * window;
|
|
|
|
GetWindow(window);
|
2009-05-07 19:31:04 -07:00
|
|
|
nsIntRect relDirtyRect = aDirtyRect.ToOutsidePixels(mOwner->PresContext()->AppUnitsPerDevPixel());
|
2008-03-10 17:10:55 -07:00
|
|
|
|
|
|
|
// we got dirty rectangle in relative window coordinates, but we
|
|
|
|
// need it in absolute units and in the (left, top, right, bottom) form
|
|
|
|
RECTL rectl;
|
2009-01-14 19:27:09 -08:00
|
|
|
rectl.xLeft = relDirtyRect.x + window->x;
|
|
|
|
rectl.yBottom = relDirtyRect.y + window->y;
|
|
|
|
rectl.xRight = rectl.xLeft + relDirtyRect.width;
|
|
|
|
rectl.yTop = rectl.yBottom + relDirtyRect.height;
|
2008-03-10 17:10:55 -07:00
|
|
|
|
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
pluginEvent.event = WM_PAINT;
|
|
|
|
pluginEvent.wParam = (uint32)aHPS;
|
|
|
|
pluginEvent.lParam = (uint32)&rectl;
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-08-06 13:48:55 -07:00
|
|
|
#if defined(MOZ_X11) || defined(MOZ_DFB)
|
2008-07-06 19:49:38 -07:00
|
|
|
void nsPluginInstanceOwner::Paint(gfxContext* aContext,
|
|
|
|
const gfxRect& aFrameRect,
|
|
|
|
const gfxRect& aDirtyRect)
|
2007-07-02 20:33:13 -07:00
|
|
|
{
|
|
|
|
if (!mInstance || !mOwner)
|
|
|
|
return;
|
|
|
|
|
2008-07-06 19:49:38 -07:00
|
|
|
// Align to device pixels where sensible
|
|
|
|
// to provide crisper and faster drawing.
|
|
|
|
gfxRect pluginRect = aFrameRect;
|
|
|
|
if (aContext->UserToDevicePixelSnapped(pluginRect)) {
|
|
|
|
pluginRect = aContext->DeviceToUser(pluginRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Round out the dirty rect to plugin pixels to ensure the plugin draws
|
|
|
|
// enough pixels for interpolation to device pixels.
|
|
|
|
gfxRect dirtyRect = aDirtyRect + -pluginRect.pos;
|
|
|
|
dirtyRect.RoundOut();
|
|
|
|
|
|
|
|
// Plugins can only draw an integer number of pixels.
|
|
|
|
//
|
|
|
|
// With translation-only transformation matrices, pluginRect is already
|
|
|
|
// pixel-aligned.
|
|
|
|
//
|
|
|
|
// With more complex transformations, modifying the scales in the
|
|
|
|
// transformation matrix could retain subpixel accuracy and let the plugin
|
|
|
|
// draw a suitable number of pixels for interpolation to device pixels in
|
|
|
|
// Renderer::Draw, but such cases are not common enough to warrant the
|
|
|
|
// effort now.
|
|
|
|
nsIntSize pluginSize(NS_lround(pluginRect.size.width),
|
|
|
|
NS_lround(pluginRect.size.height));
|
|
|
|
|
|
|
|
// Determine what the plugin needs to draw.
|
|
|
|
nsIntRect pluginDirtyRect(PRInt32(dirtyRect.pos.x),
|
|
|
|
PRInt32(dirtyRect.pos.y),
|
|
|
|
PRInt32(dirtyRect.size.width),
|
|
|
|
PRInt32(dirtyRect.size.height));
|
|
|
|
if (!pluginDirtyRect.
|
|
|
|
IntersectRect(nsIntRect(0, 0, pluginSize.width, pluginSize.height),
|
|
|
|
pluginDirtyRect))
|
2007-07-02 20:33:13 -07:00
|
|
|
return;
|
|
|
|
|
2008-07-06 19:49:38 -07:00
|
|
|
nsPluginWindow* window;
|
|
|
|
GetWindow(window);
|
|
|
|
|
|
|
|
Renderer renderer(window, mInstance, pluginSize, pluginDirtyRect);
|
2007-07-02 20:33:13 -07:00
|
|
|
PRUint32 rendererFlags =
|
|
|
|
Renderer::DRAW_SUPPORTS_OFFSET |
|
|
|
|
Renderer::DRAW_SUPPORTS_CLIP_RECT |
|
|
|
|
Renderer::DRAW_SUPPORTS_NONDEFAULT_VISUAL |
|
2008-07-07 19:15:40 -07:00
|
|
|
Renderer::DRAW_SUPPORTS_ALTERNATE_SCREEN;
|
2007-07-02 20:33:13 -07:00
|
|
|
|
|
|
|
PRBool transparent = PR_TRUE;
|
|
|
|
mInstance->GetValue(nsPluginInstanceVariable_TransparentBool,
|
|
|
|
(void *)&transparent);
|
|
|
|
if (!transparent)
|
|
|
|
rendererFlags |= Renderer::DRAW_IS_OPAQUE;
|
|
|
|
|
2008-07-06 19:49:38 -07:00
|
|
|
// Renderer::Draw() draws a rectangle with top-left at the aContext origin.
|
|
|
|
gfxContextAutoSaveRestore autoSR(aContext);
|
|
|
|
aContext->Translate(pluginRect.pos);
|
2007-07-02 20:33:13 -07:00
|
|
|
|
2008-08-06 13:48:55 -07:00
|
|
|
renderer.Draw(aContext, window->width, window->height,
|
2007-07-02 20:33:13 -07:00
|
|
|
rendererFlags, nsnull);
|
|
|
|
}
|
|
|
|
|
2008-08-06 13:48:55 -07:00
|
|
|
#ifdef MOZ_X11
|
2008-07-07 19:15:40 -07:00
|
|
|
static int
|
|
|
|
DepthOfVisual(const Screen* screen, const Visual* visual)
|
|
|
|
{
|
|
|
|
for (int d = 0; d < screen->ndepths; d++) {
|
|
|
|
Depth *d_info = &screen->depths[d];
|
|
|
|
for (int v = 0; v < d_info->nvisuals; v++) {
|
|
|
|
if (&d_info->visuals[v] == visual)
|
|
|
|
return d_info->depth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ERROR("Visual not on Screen.");
|
|
|
|
return 0;
|
|
|
|
}
|
2008-08-06 13:48:55 -07:00
|
|
|
#endif
|
2008-07-07 19:15:40 -07:00
|
|
|
|
2008-08-09 06:43:08 -07:00
|
|
|
#if defined(MOZ_WIDGET_GTK2)
|
2007-07-02 20:33:13 -07:00
|
|
|
nsresult
|
2008-08-06 13:48:55 -07:00
|
|
|
nsPluginInstanceOwner::Renderer::NativeDraw(GdkDrawable * drawable,
|
2007-07-02 20:33:13 -07:00
|
|
|
short offsetX, short offsetY,
|
2008-08-06 13:48:55 -07:00
|
|
|
GdkRectangle * clipRects,
|
2007-07-02 20:33:13 -07:00
|
|
|
PRUint32 numClipRects)
|
2008-08-06 13:48:55 -07:00
|
|
|
|
2007-07-02 20:33:13 -07:00
|
|
|
{
|
2008-08-06 13:48:55 -07:00
|
|
|
#ifdef MOZ_X11
|
|
|
|
Visual * visual = GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(drawable));
|
|
|
|
Colormap colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(drawable));
|
|
|
|
Screen * screen = GDK_SCREEN_XSCREEN (gdk_drawable_get_screen(drawable));
|
2008-08-09 06:43:08 -07:00
|
|
|
#endif
|
|
|
|
#elif defined(MOZ_WIDGET_QT)
|
|
|
|
nsresult
|
|
|
|
nsPluginInstanceOwner::Renderer::NativeDraw(QWidget * drawable,
|
|
|
|
short offsetX, short offsetY,
|
|
|
|
QRect * clipRects,
|
|
|
|
PRUint32 numClipRects)
|
|
|
|
{
|
|
|
|
#ifdef MOZ_X11
|
|
|
|
QX11Info xinfo = drawable->x11Info();
|
|
|
|
Visual * visual = (Visual*) xinfo.visual();
|
|
|
|
Colormap colormap = xinfo.colormap();
|
|
|
|
Screen * screen = (Screen*) xinfo.screen();
|
|
|
|
#endif
|
2008-08-06 13:48:55 -07:00
|
|
|
#endif
|
2007-07-02 20:33:13 -07:00
|
|
|
// See if the plugin must be notified of new window parameters.
|
|
|
|
PRBool doupdatewindow = PR_FALSE;
|
|
|
|
|
|
|
|
if (mWindow->x != offsetX || mWindow->y != offsetY) {
|
|
|
|
mWindow->x = offsetX;
|
|
|
|
mWindow->y = offsetY;
|
|
|
|
doupdatewindow = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-07-06 19:49:38 -07:00
|
|
|
if (nsIntSize(mWindow->width, mWindow->height) != mPluginSize) {
|
|
|
|
mWindow->width = mPluginSize.width;
|
|
|
|
mWindow->height = mPluginSize.height;
|
|
|
|
doupdatewindow = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
2008-07-21 01:40:41 -07:00
|
|
|
// The clip rect is relative to drawable top-left.
|
2007-07-02 20:33:13 -07:00
|
|
|
NS_ASSERTION(numClipRects <= 1, "We don't support multiple clip rectangles!");
|
2008-07-21 01:40:41 -07:00
|
|
|
nsIntRect clipRect;
|
2007-07-02 20:33:13 -07:00
|
|
|
if (numClipRects) {
|
2008-08-09 06:43:08 -07:00
|
|
|
#if defined(MOZ_WIDGET_GTK2)
|
2008-07-21 01:40:41 -07:00
|
|
|
clipRect.x = clipRects[0].x;
|
|
|
|
clipRect.y = clipRects[0].y;
|
|
|
|
clipRect.width = clipRects[0].width;
|
|
|
|
clipRect.height = clipRects[0].height;
|
2008-08-09 06:43:08 -07:00
|
|
|
#elif defined(MOZ_WIDGET_QT)
|
|
|
|
clipRect.x = clipRects[0].x();
|
|
|
|
clipRect.y = clipRects[0].y();
|
|
|
|
clipRect.width = clipRects[0].width();
|
|
|
|
clipRect.height = clipRects[0].height();
|
|
|
|
#endif
|
2007-07-02 20:33:13 -07:00
|
|
|
}
|
|
|
|
else {
|
2008-07-21 01:40:41 -07:00
|
|
|
// nsPluginRect members are unsigned, but
|
|
|
|
// we should have been given a clip if an offset is -ve.
|
2007-07-02 20:33:13 -07:00
|
|
|
NS_ASSERTION(offsetX >= 0 && offsetY >= 0,
|
|
|
|
"Clip rectangle offsets are negative!");
|
2008-07-21 01:40:41 -07:00
|
|
|
clipRect.x = offsetX;
|
|
|
|
clipRect.y = offsetY;
|
|
|
|
clipRect.width = mWindow->width;
|
|
|
|
clipRect.height = mWindow->height;
|
2007-07-02 20:33:13 -07:00
|
|
|
}
|
|
|
|
|
2008-07-21 01:40:41 -07:00
|
|
|
nsPluginRect newClipRect;
|
|
|
|
newClipRect.left = clipRect.x;
|
|
|
|
newClipRect.top = clipRect.y;
|
|
|
|
newClipRect.right = clipRect.XMost();
|
|
|
|
newClipRect.bottom = clipRect.YMost();
|
2007-07-02 20:33:13 -07:00
|
|
|
if (mWindow->clipRect.left != newClipRect.left ||
|
|
|
|
mWindow->clipRect.top != newClipRect.top ||
|
|
|
|
mWindow->clipRect.right != newClipRect.right ||
|
|
|
|
mWindow->clipRect.bottom != newClipRect.bottom) {
|
|
|
|
mWindow->clipRect = newClipRect;
|
|
|
|
doupdatewindow = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NPSetWindowCallbackStruct* ws_info =
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<NPSetWindowCallbackStruct*>(mWindow->ws_info);
|
2008-08-06 13:48:55 -07:00
|
|
|
#ifdef MOZ_X11
|
2008-07-07 19:15:40 -07:00
|
|
|
if (ws_info->visual != visual || ws_info->colormap != colormap) {
|
2007-07-02 20:33:13 -07:00
|
|
|
ws_info->visual = visual;
|
2008-07-07 19:15:40 -07:00
|
|
|
ws_info->colormap = colormap;
|
|
|
|
ws_info->depth = DepthOfVisual(screen, visual);
|
2007-07-02 20:33:13 -07:00
|
|
|
doupdatewindow = PR_TRUE;
|
|
|
|
}
|
2008-08-06 13:48:55 -07:00
|
|
|
#endif
|
2007-07-02 20:33:13 -07:00
|
|
|
|
2009-05-14 19:26:10 -07:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
if (mWindow->type == nsPluginWindowType_Drawable)
|
2009-02-25 07:25:12 -08:00
|
|
|
#endif
|
2009-05-14 19:26:10 -07:00
|
|
|
{
|
|
|
|
if (doupdatewindow)
|
|
|
|
mInstance->SetWindow(mWindow);
|
|
|
|
}
|
2007-07-02 20:33:13 -07:00
|
|
|
|
2008-08-06 13:48:55 -07:00
|
|
|
#ifdef MOZ_X11
|
2008-07-21 01:40:41 -07:00
|
|
|
// Translate the dirty rect to drawable coordinates.
|
|
|
|
nsIntRect dirtyRect = mDirtyRect + nsIntPoint(offsetX, offsetY);
|
|
|
|
// Intersect the dirty rect with the clip rect to ensure that it lies within
|
|
|
|
// the drawable.
|
|
|
|
if (!dirtyRect.IntersectRect(dirtyRect, clipRect))
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-05-14 19:26:10 -07:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
|
|
|
if (mWindow->type == nsPluginWindowType_Drawable) {
|
|
|
|
#endif
|
|
|
|
nsPluginEvent pluginEvent;
|
|
|
|
XGraphicsExposeEvent& exposeEvent =
|
|
|
|
pluginEvent.event.xgraphicsexpose;
|
|
|
|
// set the drawing info
|
|
|
|
exposeEvent.type = GraphicsExpose;
|
|
|
|
exposeEvent.display = DisplayOfScreen(screen);
|
|
|
|
exposeEvent.drawable =
|
2008-08-09 06:43:08 -07:00
|
|
|
#if defined(MOZ_WIDGET_GTK2)
|
|
|
|
GDK_DRAWABLE_XID(drawable);
|
|
|
|
#elif defined(MOZ_WIDGET_QT)
|
|
|
|
drawable->x11PictureHandle();
|
|
|
|
#endif
|
2009-05-14 19:26:10 -07:00
|
|
|
exposeEvent.x = mDirtyRect.x + offsetX;
|
|
|
|
exposeEvent.y = mDirtyRect.y + offsetY;
|
|
|
|
exposeEvent.width = mDirtyRect.width;
|
|
|
|
exposeEvent.height = mDirtyRect.height;
|
|
|
|
exposeEvent.count = 0;
|
|
|
|
// information not set:
|
|
|
|
exposeEvent.serial = 0;
|
|
|
|
exposeEvent.send_event = False;
|
|
|
|
exposeEvent.major_code = 0;
|
|
|
|
exposeEvent.minor_code = 0;
|
2007-07-02 20:33:13 -07:00
|
|
|
|
2009-05-14 19:26:10 -07:00
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
2009-02-25 07:25:12 -08:00
|
|
|
#ifdef MOZ_COMPOSITED_PLUGINS
|
2009-05-14 19:26:10 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* XXX: this is very nasty. We need a better way of getting at mPlugWindow */
|
|
|
|
GtkWidget *plug = (GtkWidget*)(((nsPluginNativeWindow*)mWindow)->mPlugWindow);
|
|
|
|
//GtkWidget *plug = (GtkWidget*)(((nsPluginNativeWindowGtk2*)mWindow)->mSocketWidget);
|
|
|
|
|
|
|
|
/* Cairo has bugs with IncludeInferiors when using paint
|
|
|
|
* so we use XCopyArea directly instead. */
|
|
|
|
XGCValues gcv;
|
|
|
|
gcv.subwindow_mode = IncludeInferiors;
|
|
|
|
gcv.graphics_exposures = False;
|
|
|
|
GC gc = XCreateGC(GDK_DISPLAY(), gdk_x11_drawable_get_xid(drawable), GCGraphicsExposures | GCSubwindowMode, &gcv);
|
|
|
|
/* The source and destination appear to always line up, so src and dest
|
|
|
|
* coords should be the same */
|
|
|
|
XCopyArea(GDK_DISPLAY(), gdk_x11_drawable_get_xid(plug->window),
|
|
|
|
gdk_x11_drawable_get_xid(drawable),
|
|
|
|
gc,
|
|
|
|
mDirtyRect.x,
|
|
|
|
mDirtyRect.y,
|
|
|
|
mDirtyRect.width,
|
|
|
|
mDirtyRect.height,
|
|
|
|
mDirtyRect.x,
|
|
|
|
mDirtyRect.y);
|
|
|
|
XFreeGC(GDK_DISPLAY(), gc);
|
|
|
|
}
|
|
|
|
#endif
|
2009-02-25 07:25:12 -08:00
|
|
|
#endif
|
2007-07-02 20:33:13 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-07-02 20:33:13 -07:00
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Here's how we give idle time to plugins.
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* timer)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
#ifdef XP_MACOSX
|
2009-08-26 17:29:47 -07:00
|
|
|
if (GetEventModel() != NPEventModelCarbon)
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-06-15 14:36:11 -07:00
|
|
|
// validate the plugin clipping information by syncing the plugin window info to
|
|
|
|
// reflect the current widget location. This makes sure that everything is updated
|
|
|
|
// correctly in the event of scrolling in the window.
|
|
|
|
if (mInstance) {
|
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
|
2009-08-26 17:29:47 -07:00
|
|
|
void* window = FixUpPluginWindow(ePluginPaintEnable);
|
2009-06-15 14:36:11 -07:00
|
|
|
if (window) {
|
|
|
|
EventRecord idleEvent;
|
2009-08-04 18:36:37 -07:00
|
|
|
InitializeEventRecord(&idleEvent, nsnull);
|
2009-06-15 14:36:11 -07:00
|
|
|
idleEvent.what = nullEvent;
|
|
|
|
|
|
|
|
// give a bogus 'where' field of our null event when hidden, so Flash
|
|
|
|
// won't respond to mouse moves in other tabs, see bug 120875
|
|
|
|
if (!mWidgetVisible)
|
|
|
|
idleEvent.where.h = idleEvent.where.v = 20000;
|
|
|
|
|
|
|
|
nsPluginEvent pluginEvent = { &idleEvent, nsPluginPlatformWindowRef(window) };
|
|
|
|
|
|
|
|
PRBool eventHandled = PR_FALSE;
|
|
|
|
mInstance->HandleEvent(&pluginEvent, &eventHandled);
|
|
|
|
}
|
|
|
|
|
|
|
|
pluginWidget->EndDrawPlugin();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2009-06-15 14:36:11 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2009-06-15 14:36:11 -07:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsPluginInstanceOwner::StartTimer(unsigned int aDelay)
|
|
|
|
{
|
|
|
|
#ifdef XP_MACOSX
|
2009-08-26 17:29:47 -07:00
|
|
|
if (GetEventModel() != NPEventModelCarbon)
|
|
|
|
return;
|
|
|
|
|
2008-12-03 01:30:40 -08:00
|
|
|
if (!mTimerCanceled)
|
|
|
|
return;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-12-03 01:30:40 -08:00
|
|
|
// start a periodic timer to provide null events to the plugin instance.
|
|
|
|
if (!mPluginTimer) {
|
|
|
|
mPluginTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
}
|
|
|
|
if (mPluginTimer) {
|
|
|
|
mTimerCanceled = PR_FALSE;
|
|
|
|
mPluginTimer->InitWithCallback(this, aDelay, nsITimer::TYPE_REPEATING_SLACK);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsPluginInstanceOwner::CancelTimer()
|
|
|
|
{
|
2008-08-25 23:53:00 -07:00
|
|
|
if (mPluginTimer) {
|
|
|
|
mPluginTimer->Cancel();
|
|
|
|
}
|
2008-12-03 01:30:40 -08:00
|
|
|
mTimerCanceled = PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsPluginInstanceOwner::Init(nsPresContext* aPresContext,
|
|
|
|
nsObjectFrame* aFrame,
|
|
|
|
nsIContent* aContent)
|
|
|
|
{
|
2009-02-02 17:23:48 -08:00
|
|
|
mLastEventloopNestingLevel = GetEventloopNestingLevel();
|
2008-03-25 09:56:04 -07:00
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("nsPluginInstanceOwner::Init() called on %p for frame %p\n", this,
|
|
|
|
aFrame));
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
mOwner = aFrame;
|
|
|
|
mContent = aContent;
|
2008-02-28 18:06:00 -08:00
|
|
|
|
|
|
|
nsWeakFrame weakFrame(aFrame);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Some plugins require a specific sequence of shutdown and startup when
|
|
|
|
// a page is reloaded. Shutdown happens usually when the last instance
|
|
|
|
// is destroyed. Here we make sure the plugin instance in the old
|
|
|
|
// document is destroyed before we try to create the new one.
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
aPresContext->EnsureVisible();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-02-28 18:06:00 -08:00
|
|
|
if (!weakFrame.IsAlive()) {
|
|
|
|
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
|
|
|
("nsPluginInstanceOwner::Init's EnsureVisible() call destroyed "
|
|
|
|
"instance owner %p\n", this));
|
|
|
|
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// register context menu listener
|
|
|
|
mCXMenuListener = new nsPluginDOMContextMenuListener();
|
|
|
|
if (mCXMenuListener) {
|
|
|
|
mCXMenuListener->Init(aContent);
|
|
|
|
}
|
|
|
|
|
2007-05-14 02:11:38 -07:00
|
|
|
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mContent));
|
|
|
|
if (target) {
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventListener> listener;
|
|
|
|
QueryInterface(NS_GET_IID(nsIDOMEventListener), getter_AddRefs(listener));
|
|
|
|
|
|
|
|
// Register focus listener
|
2007-05-14 02:11:38 -07:00
|
|
|
mContent->AddEventListenerByIID(listener, NS_GET_IID(nsIDOMFocusListener));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Register mouse listener
|
2007-05-14 02:11:38 -07:00
|
|
|
mContent->AddEventListenerByIID(listener, NS_GET_IID(nsIDOMMouseListener));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// now do the mouse motion listener
|
2007-05-14 02:11:38 -07:00
|
|
|
mContent->AddEventListenerByIID(listener, NS_GET_IID(nsIDOMMouseMotionListener));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Register key listener
|
2007-05-14 02:11:38 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("keypress"), listener, PR_TRUE);
|
|
|
|
target->AddEventListener(NS_LITERAL_STRING("keydown"), listener, PR_TRUE);
|
|
|
|
target->AddEventListener(NS_LITERAL_STRING("keyup"), listener, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Register drag listener
|
2008-10-17 13:04:55 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("drop"), listener, PR_TRUE);
|
2007-05-14 02:11:38 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("dragdrop"), listener, PR_TRUE);
|
2008-10-17 13:04:55 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("drag"), listener, PR_TRUE);
|
|
|
|
target->AddEventListener(NS_LITERAL_STRING("dragenter"), listener, PR_TRUE);
|
2007-05-14 02:11:38 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("dragover"), listener, PR_TRUE);
|
2008-10-17 13:04:55 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("dragleave"), listener, PR_TRUE);
|
2007-05-14 02:11:38 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("dragexit"), listener, PR_TRUE);
|
2008-10-17 13:04:55 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("dragstart"), listener, PR_TRUE);
|
2007-05-14 02:11:38 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("draggesture"), listener, PR_TRUE);
|
2008-10-17 13:04:55 -07:00
|
|
|
target->AddEventListener(NS_LITERAL_STRING("dragend"), listener, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Register scroll position listener
|
|
|
|
// We need to register a scroll pos listener on every scrollable
|
|
|
|
// view up to the top
|
|
|
|
nsIFrame* parentWithView = mOwner->GetAncestorWithView();
|
|
|
|
nsIView* curView = parentWithView ? parentWithView->GetView() : nsnull;
|
|
|
|
while (curView) {
|
|
|
|
nsIScrollableView* scrollingView = curView->ToScrollableView();
|
|
|
|
if (scrollingView)
|
|
|
|
scrollingView->AddScrollPositionListener((nsIScrollPositionListener *)this);
|
|
|
|
|
|
|
|
curView = curView->GetParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPluginPort* nsPluginInstanceOwner::GetPluginPort()
|
|
|
|
{
|
|
|
|
//!!! Port must be released for windowless plugins on Windows, because it is HDC !!!
|
|
|
|
|
|
|
|
nsPluginPort* result = NULL;
|
|
|
|
if (mWidget) {
|
|
|
|
#ifdef XP_WIN
|
|
|
|
if (mPluginWindow && mPluginWindow->type == nsPluginWindowType_Drawable)
|
|
|
|
result = (nsPluginPort*) mWidget->GetNativeData(NS_NATIVE_GRAPHIC);
|
|
|
|
else
|
2007-03-26 18:07:57 -07:00
|
|
|
#endif
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
if (GetDrawingModel() == NPDrawingModelCoreGraphics)
|
|
|
|
result = (nsPluginPort*) mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG);
|
|
|
|
else
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
result = (nsPluginPort*) mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsPluginInstanceOwner::ReleasePluginPort(nsPluginPort * pluginPort)
|
|
|
|
{
|
|
|
|
#ifdef XP_WIN
|
|
|
|
if (mWidget && mPluginWindow &&
|
|
|
|
mPluginWindow->type == nsPluginWindowType_Drawable) {
|
|
|
|
mWidget->FreeNativeData((HDC)pluginPort, NS_NATIVE_GRAPHIC);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(mPluginWindow, NS_ERROR_NULL_POINTER);
|
|
|
|
|
|
|
|
nsIView *view;
|
|
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
if (mOwner) {
|
|
|
|
// Create view if necessary
|
|
|
|
|
|
|
|
view = mOwner->GetView();
|
|
|
|
|
|
|
|
if (!view || !mWidget) {
|
|
|
|
PRBool windowless = PR_FALSE;
|
|
|
|
|
|
|
|
mInstance->GetValue(nsPluginInstanceVariable_WindowlessBool,
|
|
|
|
(void *)&windowless);
|
|
|
|
|
|
|
|
// always create widgets in Twips, not pixels
|
2007-03-30 14:11:41 -07:00
|
|
|
nsPresContext* context = mOwner->PresContext();
|
2007-03-22 10:30:00 -07:00
|
|
|
rv = mOwner->CreateWidget(context->DevPixelsToAppUnits(mPluginWindow->width),
|
|
|
|
context->DevPixelsToAppUnits(mPluginWindow->height),
|
|
|
|
windowless);
|
|
|
|
if (NS_OK == rv) {
|
2009-07-21 17:45:00 -07:00
|
|
|
mWidget = mOwner->GetWidget();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (PR_TRUE == windowless) {
|
|
|
|
mPluginWindow->type = nsPluginWindowType_Drawable;
|
|
|
|
|
|
|
|
// this needs to be a HDC according to the spec, but I do
|
|
|
|
// not see the right way to release it so let's postpone
|
|
|
|
// passing HDC till paint event when it is really
|
|
|
|
// needed. Change spec?
|
|
|
|
mPluginWindow->window = nsnull;
|
2008-07-07 19:15:40 -07:00
|
|
|
#ifdef MOZ_X11
|
|
|
|
// Fill in the display field.
|
|
|
|
nsIWidget* win = mOwner->GetWindow();
|
|
|
|
NPSetWindowCallbackStruct* ws_info =
|
|
|
|
static_cast<NPSetWindowCallbackStruct*>(mPluginWindow->ws_info);
|
|
|
|
if (win) {
|
|
|
|
ws_info->display =
|
|
|
|
static_cast<Display*>(win->GetNativeData(NS_NATIVE_DISPLAY));
|
|
|
|
}
|
|
|
|
#ifdef MOZ_WIDGET_GTK2
|
|
|
|
else {
|
|
|
|
ws_info->display = GDK_DISPLAY();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
} else if (mWidget) {
|
|
|
|
mWidget->Resize(mPluginWindow->width, mPluginWindow->height,
|
|
|
|
PR_FALSE);
|
|
|
|
|
|
|
|
// mPluginWindow->type is used in |GetPluginPort| so it must
|
2008-04-23 15:56:40 -07:00
|
|
|
// be initialized first
|
2007-03-22 10:30:00 -07:00
|
|
|
mPluginWindow->type = nsPluginWindowType_Window;
|
|
|
|
mPluginWindow->window = GetPluginPort();
|
|
|
|
|
|
|
|
// start the idle timer.
|
|
|
|
StartTimer(NORMAL_PLUGIN_DELAY);
|
|
|
|
|
|
|
|
// tell the plugin window about the widget
|
|
|
|
mPluginWindow->SetPluginWidget(mWidget);
|
2008-04-23 15:56:40 -07:00
|
|
|
|
|
|
|
// tell the widget about the current plugin instance owner.
|
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (pluginWidget)
|
|
|
|
pluginWidget->SetPluginInstanceOwner(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
|
|
|
|
{
|
|
|
|
mPluginHost = aHost;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mac specific code to fix up the port location and clipping region
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-03-13 20:31:35 -07:00
|
|
|
if (!mWidget || !mPluginWindow || !mInstance || !mOwner)
|
2007-03-22 10:30:00 -07:00
|
|
|
return nsnull;
|
|
|
|
|
2008-10-30 10:40:53 -07:00
|
|
|
NPDrawingModel drawingModel = GetDrawingModel();
|
2009-08-26 17:29:47 -07:00
|
|
|
NPEventModel eventModel = GetEventModel();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
|
|
|
|
if (!pluginWidget)
|
|
|
|
return nsnull;
|
|
|
|
|
|
|
|
pluginWidget->SetPluginEventModel(eventModel);
|
2008-10-30 10:40:53 -07:00
|
|
|
|
|
|
|
// If we've already set up a CGContext in nsObjectFrame::PaintPlugin(), we
|
|
|
|
// don't want calls to SetPluginPortAndDetectChange() to step on our work.
|
|
|
|
nsPluginPort* pluginPort = nsnull;
|
|
|
|
if (mInCGPaintLevel > 0) {
|
|
|
|
pluginPort = mPluginWindow->window;
|
|
|
|
} else {
|
|
|
|
pluginPort = SetPluginPortAndDetectChange();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (!pluginPort)
|
|
|
|
return nsnull;
|
|
|
|
|
2009-01-14 19:27:09 -08:00
|
|
|
nsIntPoint pluginOrigin;
|
|
|
|
nsIntRect widgetClip;
|
2007-03-22 10:30:00 -07:00
|
|
|
PRBool widgetVisible;
|
2009-06-19 09:15:23 -07:00
|
|
|
pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin, widgetVisible);
|
2009-07-21 17:45:00 -07:00
|
|
|
mWidgetVisible = widgetVisible;
|
2009-06-19 09:15:23 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// printf("GetPluginClipRect returning visible %d\n", widgetVisible);
|
|
|
|
|
2007-03-26 18:07:57 -07:00
|
|
|
#ifndef NP_NO_QUICKDRAW
|
2007-03-22 10:30:00 -07:00
|
|
|
// set the port coordinates
|
2007-03-26 18:07:57 -07:00
|
|
|
if (drawingModel == NPDrawingModelQuickDraw) {
|
|
|
|
mPluginWindow->x = -pluginPort->qdPort.portx;
|
|
|
|
mPluginWindow->y = -pluginPort->qdPort.porty;
|
|
|
|
}
|
2007-06-02 15:02:57 -07:00
|
|
|
else if (drawingModel == NPDrawingModelCoreGraphics)
|
2007-03-26 18:07:57 -07:00
|
|
|
#endif
|
2007-06-02 15:02:57 -07:00
|
|
|
{
|
|
|
|
// This would be a lot easier if we could use obj-c here,
|
|
|
|
// but we can't. Since we have only nsIWidget and we can't
|
|
|
|
// use its native widget (an obj-c object) we have to go
|
|
|
|
// from the widget's screen coordinates to its window coords
|
|
|
|
// instead of straight to window coords.
|
2009-02-18 16:11:49 -08:00
|
|
|
nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
|
2007-06-02 15:02:57 -07:00
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
nsRect windowRect;
|
|
|
|
if (eventModel == NPEventModelCarbon)
|
|
|
|
NS_NPAPI_CarbonWindowFrame(static_cast<WindowRef>(pluginPort->cgPort.window), windowRect);
|
|
|
|
else
|
|
|
|
NS_NPAPI_CocoaWindowFrame(pluginPort->cgPort.window, windowRect);
|
2007-06-02 15:02:57 -07:00
|
|
|
|
2009-08-26 17:29:47 -07:00
|
|
|
mPluginWindow->x = geckoScreenCoords.x - windowRect.x;
|
|
|
|
mPluginWindow->y = geckoScreenCoords.y - windowRect.y;
|
2007-06-02 15:02:57 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsPluginRect oldClipRect = mPluginWindow->clipRect;
|
|
|
|
|
|
|
|
// fix up the clipping region
|
|
|
|
mPluginWindow->clipRect.top = widgetClip.y;
|
|
|
|
mPluginWindow->clipRect.left = widgetClip.x;
|
|
|
|
|
|
|
|
if (!mWidgetVisible || inPaintState == ePluginPaintDisable) {
|
|
|
|
mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
|
|
|
|
mPluginWindow->clipRect.right = mPluginWindow->clipRect.left;
|
|
|
|
// pluginPort = nsnull; // don't uncomment this
|
|
|
|
}
|
|
|
|
else if (inPaintState == ePluginPaintEnable)
|
|
|
|
{
|
|
|
|
mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top + widgetClip.height;
|
|
|
|
mPluginWindow->clipRect.right = mPluginWindow->clipRect.left + widgetClip.width;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the clip rect changed, call SetWindow()
|
|
|
|
// (RealPlayer needs this to draw correctly)
|
|
|
|
if (mPluginWindow->clipRect.left != oldClipRect.left ||
|
|
|
|
mPluginWindow->clipRect.top != oldClipRect.top ||
|
|
|
|
mPluginWindow->clipRect.right != oldClipRect.right ||
|
|
|
|
mPluginWindow->clipRect.bottom != oldClipRect.bottom)
|
|
|
|
{
|
|
|
|
mInstance->SetWindow(mPluginWindow);
|
2008-10-30 10:40:53 -07:00
|
|
|
mPluginPortChanged = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
// if the clipRect is of size 0, make the null timer fire less often
|
|
|
|
CancelTimer();
|
|
|
|
if (mPluginWindow->clipRect.left == mPluginWindow->clipRect.right ||
|
|
|
|
mPluginWindow->clipRect.top == mPluginWindow->clipRect.bottom) {
|
|
|
|
StartTimer(HIDDEN_PLUGIN_DELAY);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
StartTimer(NORMAL_PLUGIN_DELAY);
|
|
|
|
}
|
2008-10-30 10:40:53 -07:00
|
|
|
} else if (mPluginPortChanged) {
|
2008-10-17 15:22:10 -07:00
|
|
|
mInstance->SetWindow(mPluginWindow);
|
2008-10-30 10:40:53 -07:00
|
|
|
mPluginPortChanged = PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-03-26 18:07:57 -07:00
|
|
|
#ifndef NP_NO_QUICKDRAW
|
|
|
|
if (drawingModel == NPDrawingModelQuickDraw)
|
|
|
|
return ::GetWindowFromPort(pluginPort->qdPort.port);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (drawingModel == NPDrawingModelCoreGraphics)
|
|
|
|
return pluginPort->cgPort.window;
|
|
|
|
|
|
|
|
return nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // XP_MACOSX
|
|
|
|
|
|
|
|
// Little helper function to resolve relative URL in
|
|
|
|
// |value| for certain inputs of |name|
|
|
|
|
void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
|
|
|
|
{
|
|
|
|
if (name.LowerCaseEqualsLiteral("pluginurl") ||
|
|
|
|
name.LowerCaseEqualsLiteral("pluginspage")) {
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
|
|
|
|
nsAutoString newURL;
|
|
|
|
NS_MakeAbsoluteURI(newURL, value, baseURI);
|
|
|
|
if (!newURL.IsEmpty())
|
|
|
|
value = newURL;
|
|
|
|
}
|
|
|
|
}
|