Implement Cocoa NPAPI event model. b=435041 sr=roc

This commit is contained in:
Josh Aas 2009-08-26 17:29:47 -07:00
Родитель 2b712e51ce
Коммит d8264ff87b
19 изменённых файлов: 1279 добавлений и 254 удалений

Просмотреть файл

@ -407,11 +407,13 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIPLUGININSTANCEOWNER
// XXXjst: What's up with nsIPluginInstanceOwner and these functions?
NS_IMETHOD GetURL(const char *aURL, const char *aTarget, void *aPostData,
PRUint32 aPostDataLen, void *aHeadersData,
PRUint32 aHeadersDataLen, PRBool aIsFile = PR_FALSE);
NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
NPError ShowNativeContextMenu(NPMenu* menu, nsPluginEvent* event);
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace);
NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner)
@ -505,6 +507,19 @@ nsDummyJavaPluginOwner::ShowStatus(const PRUnichar *aStatusMsg)
return NS_ERROR_NOT_IMPLEMENTED;
}
NPError
nsDummyJavaPluginOwner::ShowNativeContextMenu(NPMenu* menu, nsPluginEvent* event)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NPBool
nsDummyJavaPluginOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace)
{
return PR_FALSE;
}
NS_IMETHODIMP
nsDummyJavaPluginOwner::GetDocument(nsIDocument **aDocument)
{

Просмотреть файл

@ -136,6 +136,12 @@ CPPSRCS += \
$(NULL)
endif
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
CMMSRCS += \
nsPluginUtilsOSX.mm \
$(NULL)
endif
RESOURCES_HTML = \
$(srcdir)/folder.png \
$(NULL)

Просмотреть файл

@ -158,6 +158,7 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#ifdef XP_MACOSX
#include "gfxQuartzNativeDrawing.h"
#include "nsPluginUtilsOSX.h"
#endif
#ifdef MOZ_X11
@ -280,6 +281,11 @@ public:
NS_IMETHOD GetNetscapeWindow(void *value);
NPError ShowNativeContextMenu(NPMenu* menu, nsPluginEvent* event);
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace);
//nsIPluginTagInfo interface
NS_IMETHOD GetAttributes(PRUint16& n, const char*const*& names,
@ -345,7 +351,7 @@ public:
#ifdef XP_WIN
void Paint(const RECT& aDirty, HDC aDC);
#elif defined(XP_MACOSX)
void Paint();
void Paint(const gfxRect& aDirtyRect);
#elif defined(MOZ_X11) || defined(MOZ_DFB)
void Paint(gfxContext* aContext,
const gfxRect& aFrameRect,
@ -378,7 +384,8 @@ public:
#ifdef XP_MACOSX
NPDrawingModel GetDrawingModel();
WindowRef FixUpPluginWindow(PRInt32 inPaintState);
NPEventModel GetEventModel();
void* FixUpPluginWindow(PRInt32 inPaintState);
// 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; }
@ -1599,7 +1606,7 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
}
mInstanceOwner->BeginCGPaint();
mInstanceOwner->Paint();
mInstanceOwner->Paint(nativeClipRect - offset);
mInstanceOwner->EndCGPaint();
nativeDrawing.EndNativeDrawing();
@ -1608,7 +1615,9 @@ nsObjectFrame::PaintPlugin(nsIRenderingContext& aRenderingContext,
nsIRenderingContext::AutoPushTranslation
translate(&aRenderingContext, aFramePt.x, aFramePt.y);
mInstanceOwner->Paint();
// this rect is used only in the CoreGraphics drawing model
gfxRect tmpRect(0, 0, 0, 0);
mInstanceOwner->Paint(tmpRect);
}
}
#elif defined(MOZ_X11) || defined(MOZ_DFB)
@ -1856,6 +1865,7 @@ nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
nsGUIEvent* anEvent,
nsEventStatus* anEventStatus)
{
NS_ENSURE_ARG_POINTER(anEvent);
NS_ENSURE_ARG_POINTER(anEventStatus);
nsresult rv = NS_OK;
@ -1881,6 +1891,14 @@ nsObjectFrame::HandleEvent(nsPresContext* aPresContext,
return rv;
#endif
#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
switch (anEvent->message) {
case NS_DESTROY:
mInstanceOwner->CancelTimer();
@ -2123,8 +2141,6 @@ DoStopPlugin(nsPluginInstanceOwner *aInstanceOwner, PRBool aDelayedStop)
inst->GetValue(nsPluginInstanceVariable_CallSetWindowAfterDestroyBool,
(void *)&doCallSetWindowAfterDestroy);
if (doCallSetWindowAfterDestroy) {
// XXXjst: ns4xPluginInstance::Destroy() is a no-op, clean
// this mess up when there are no other instance types.
inst->Stop();
if (window)
@ -2808,6 +2824,37 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetNetscapeWindow(void *value)
#endif
}
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
}
NS_IMETHODIMP nsPluginInstanceOwner::GetTagType(nsPluginTagType *result)
{
NS_ENSURE_ARG_POINTER(result);
@ -3341,6 +3388,11 @@ static void InitializeEventRecord(EventRecord* event, Point* aMousePosition)
event->modifiers = ::GetCurrentEventKeyModifiers();
}
static void InitializeNPCocoaEvent(NPCocoaEvent* event)
{
memset(event, 0, sizeof(NPCocoaEvent));
}
NPDrawingModel nsPluginInstanceOwner::GetDrawingModel()
{
#ifndef NP_NO_QUICKDRAW
@ -3358,6 +3410,23 @@ NPDrawingModel nsPluginInstanceOwner::GetDrawingModel()
return drawingModel;
}
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;
}
// 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
@ -3409,7 +3478,7 @@ void nsPluginInstanceOwner::BeginCGPaint()
void nsPluginInstanceOwner::EndCGPaint()
{
--mInCGPaintLevel;
NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPlugin()!");
NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!");
}
#endif
@ -3443,6 +3512,9 @@ nsPluginInstanceOwner::GetEventloopNestingLevel()
nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
{
#ifdef XP_MACOSX
if (GetEventModel() != NPEventModelCarbon)
return NS_OK;
CancelTimer();
if (mInstance) {
@ -3452,7 +3524,7 @@ nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScr
InitializeEventRecord(&scrollEvent, nsnull);
scrollEvent.what = NPEventType_ScrollingBeginsEvent;
WindowRef window = FixUpPluginWindow(ePluginPaintDisable);
void* window = FixUpPluginWindow(ePluginPaintDisable);
if (window) {
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(window) };
PRBool eventHandled = PR_FALSE;
@ -3468,6 +3540,9 @@ nsresult nsPluginInstanceOwner::ScrollPositionWillChange(nsIScrollableView* aScr
nsresult nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
{
#ifdef XP_MACOSX
if (GetEventModel() != NPEventModelCarbon)
return NS_OK;
if (mInstance) {
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
@ -3475,7 +3550,7 @@ nsresult nsPluginInstanceOwner::ScrollPositionDidChange(nsIScrollableView* aScro
InitializeEventRecord(&scrollEvent, nsnull);
scrollEvent.what = NPEventType_ScrollingEndsEvent;
WindowRef window = FixUpPluginWindow(ePluginPaintEnable);
void* window = FixUpPluginWindow(ePluginPaintEnable);
if (window) {
nsPluginEvent pluginEvent = { &scrollEvent, nsPluginPlatformWindowRef(window) };
PRBool eventHandled = PR_FALSE;
@ -3546,7 +3621,10 @@ nsresult nsPluginInstanceOwner::KeyUp(nsIDOMEvent* aKeyEvent)
nsresult nsPluginInstanceOwner::KeyPress(nsIDOMEvent* aKeyEvent)
{
#ifdef XP_MACOSX // send KeyPress events only on Mac
#ifdef XP_MACOSX
// send KeyPress events only for Mac OS X Carbon event model
if (GetEventModel() != NPEventModelCarbon)
return aKeyEvent->PreventDefault();
// KeyPress events are really synthesized keyDown events.
// Here we check the native message of the event so that
@ -4071,54 +4149,97 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const nsGUIEvent& anEvent)
#endif
nsEventStatus rv = nsEventStatus_eIgnore;
if (!mInstance || !mOwner) // if mInstance is null, we shouldn't be here
return rv;
return nsEventStatus_eIgnore;
#ifdef XP_MACOSX
// check for null mWidget
if (mWidget) {
// we never care about synthesized mouse enter
if (anEvent.message == NS_MOUSE_ENTER_SYNTH)
return nsEventStatus_eIgnore;
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
EventRecord carbonEvent;
NPEventModel eventModel = GetEventModel();
// If we have to synthesize an event we'll use one of these.
EventRecord synthCarbonEvent;
NPCocoaEvent synthCocoaEvent;
void* event = anEvent.nativeMsg;
if (!event || (static_cast<EventRecord*>(event)->what == nullEvent)) {
event = &carbonEvent;
if (!event) {
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mOwner);
nsPresContext* presContext = mOwner->PresContext();
nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x),
presContext->AppUnitsToDevPixels(pt.y));
Point carbonPt = { ptPx.y + mPluginWindow->y, ptPx.x + mPluginWindow->x };
InitializeEventRecord(&carbonEvent, &carbonPt);
if (eventModel == NPEventModelCarbon) {
Point carbonPt = { ptPx.y + mPluginWindow->y, ptPx.x + mPluginWindow->x };
event = &synthCarbonEvent;
InitializeEventRecord(&synthCarbonEvent, &carbonPt);
} else {
event = &synthCocoaEvent;
InitializeNPCocoaEvent(&synthCocoaEvent);
}
switch (anEvent.message) {
case NS_FOCUS_CONTENT:
case NS_BLUR_CONTENT:
carbonEvent.what = (anEvent.message == NS_FOCUS_CONTENT) ?
if (eventModel == NPEventModelCarbon) {
synthCarbonEvent.what = (anEvent.message == NS_FOCUS_CONTENT) ?
NPEventType_GetFocusEvent : NPEventType_LoseFocusEvent;
} else {
synthCocoaEvent.type = NPCocoaEventFocusChanged;
synthCocoaEvent.data.focus.hasFocus = (anEvent.message == NS_FOCUS_CONTENT);
}
break;
case NS_MOUSE_MOVE:
carbonEvent.what = osEvt;
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);
}
break;
case NS_MOUSE_BUTTON_DOWN:
carbonEvent.what = mouseDown;
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);
}
break;
case NS_MOUSE_BUTTON_UP:
carbonEvent.what = mouseUp;
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);
}
break;
}
} else if ((eventModel == NPEventModelCarbon) && (static_cast<EventRecord*>(event)->what == nullEvent)) {
Point carbonPt = { 20000, 20000 };
InitializeEventRecord(&synthCarbonEvent, &carbonPt);
event = &synthCarbonEvent;
}
if (anEvent.message == NS_FOCUS_CONTENT) {
// 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.
// 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)
::DeactivateTSMDocument(::TSMGetActiveDocument());
}
PRBool eventHandled = PR_FALSE;
WindowRef window = FixUpPluginWindow(ePluginPaintEnable);
if (window) {
nsPluginEvent pluginEvent = { (EventRecord*)event, nsPluginPlatformWindowRef(window) };
void* window = FixUpPluginWindow(ePluginPaintEnable);
if (window || (eventModel == NPEventModelCocoa)) {
nsPluginEvent pluginEvent = { event, nsPluginPlatformWindowRef(window) };
mInstance->HandleEvent(&pluginEvent, &eventHandled);
}
@ -4520,20 +4641,35 @@ nsPluginInstanceOwner::PrepareToStop(PRBool aDelayedStop)
// Paints are handled differently, so we just simulate an update event.
#ifdef XP_MACOSX
void nsPluginInstanceOwner::Paint()
void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect)
{
if (!mInstance || !mOwner)
return;
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) {
WindowRef window = FixUpPluginWindow(ePluginPaintEnable);
if (window) {
void* window = FixUpPluginWindow(ePluginPaintEnable);
if (GetEventModel() == NPEventModelCarbon && window) {
EventRecord updateEvent;
InitializeEventRecord(&updateEvent, nsnull);
updateEvent.what = updateEvt;
updateEvent.message = UInt32(window);
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();
nsPluginEvent pluginEvent = { &updateEvent, nsPluginPlatformWindowRef(window) };
PRBool eventHandled = PR_FALSE;
mInstance->HandleEvent(&pluginEvent, &eventHandled);
@ -4840,16 +4976,19 @@ nsPluginInstanceOwner::Renderer::NativeDraw(QWidget * drawable,
// Here's how we give idle time to plugins.
NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* /* timer */)
NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* timer)
{
#ifdef XP_MACOSX
if (GetEventModel() != NPEventModelCarbon)
return NS_OK;
// 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())) {
WindowRef window = FixUpPluginWindow(ePluginPaintEnable);
void* window = FixUpPluginWindow(ePluginPaintEnable);
if (window) {
EventRecord idleEvent;
InitializeEventRecord(&idleEvent, nsnull);
@ -4876,6 +5015,9 @@ NS_IMETHODIMP nsPluginInstanceOwner::Notify(nsITimer* /* timer */)
void nsPluginInstanceOwner::StartTimer(unsigned int aDelay)
{
#ifdef XP_MACOSX
if (GetEventModel() != NPEventModelCarbon)
return;
if (!mTimerCanceled)
return;
@ -5097,12 +5239,19 @@ void nsPluginInstanceOwner::SetPluginHost(nsIPluginHost* aHost)
// Mac specific code to fix up the port location and clipping region
#ifdef XP_MACOSX
WindowRef nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
void* nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
{
if (!mWidget || !mPluginWindow || !mInstance || !mOwner)
return nsnull;
NPDrawingModel drawingModel = GetDrawingModel();
NPEventModel eventModel = GetEventModel();
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
if (!pluginWidget)
return nsnull;
pluginWidget->SetPluginEventModel(eventModel);
// If we've already set up a CGContext in nsObjectFrame::PaintPlugin(), we
// don't want calls to SetPluginPortAndDetectChange() to step on our work.
@ -5116,8 +5265,6 @@ WindowRef nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
if (!pluginPort)
return nsnull;
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(mWidget);
nsIntPoint pluginOrigin;
nsIntRect widgetClip;
PRBool widgetVisible;
@ -5142,12 +5289,14 @@ WindowRef nsPluginInstanceOwner::FixUpPluginWindow(PRInt32 inPaintState)
// instead of straight to window coords.
nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset();
Rect windowRect;
WindowRef window = (WindowRef)pluginPort->cgPort.window;
::GetWindowBounds(window, kWindowStructureRgn, &windowRect);
nsRect windowRect;
if (eventModel == NPEventModelCarbon)
NS_NPAPI_CarbonWindowFrame(static_cast<WindowRef>(pluginPort->cgPort.window), windowRect);
else
NS_NPAPI_CocoaWindowFrame(pluginPort->cgPort.window, windowRect);
mPluginWindow->x = geckoScreenCoords.x - windowRect.left;
mPluginWindow->y = geckoScreenCoords.y - windowRect.top;
mPluginWindow->x = geckoScreenCoords.x - windowRect.x;
mPluginWindow->y = geckoScreenCoords.y - windowRect.y;
}
nsPluginRect oldClipRect = mPluginWindow->clipRect;

Просмотреть файл

@ -0,0 +1,61 @@
/* -*- 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.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Aas <josh@mozilla.com>
*
* 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 ***** */
// We can use Carbon in this header but not Cocoa. Cocoa pointers must be void.
#import <Carbon/Carbon.h>
#include "nsRect.h"
#include "nsIWidget.h"
#include "npapi.h"
// We use void pointers to avoid exporting native event types to cross-platform code.
// Get the rect for an entire top-level Carbon window in screen coords.
void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect);
// Get the rect for an entire top-level Cocoa window in screen coords.
void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect);
// Puts up a Cocoa context menu (NSMenu) for a particular NPCocoaEvent.
NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event);
NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace);

Просмотреть файл

@ -0,0 +1,215 @@
/* -*- 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.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Aas <josh@mozilla.com>
*
* 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 ***** */
#include "nsPluginUtilsOSX.h"
#import <Cocoa/Cocoa.h>
#include "nsObjCExceptions.h"
void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect)
{
if (!aWindow)
return;
Rect windowRect;
::GetWindowBounds(aWindow, kWindowStructureRgn, &windowRect);
outRect.x = windowRect.left;
outRect.y = windowRect.top;
outRect.width = windowRect.right - windowRect.left;
outRect.height = windowRect.bottom - windowRect.top;
}
void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!aWindow)
return;
NSWindow* window = (NSWindow*)aWindow;
float menubarScreenHeight;
NSArray* allScreens = [NSScreen screens];
if ([allScreens count])
menubarScreenHeight = [[allScreens objectAtIndex:0] frame].size.height;
else
return; // If there are no screens, there's not much we can say.
NSRect frame = [window frame];
outRect.x = (nscoord)frame.origin.x;
outRect.y = (nscoord)(menubarScreenHeight - (frame.origin.y + frame.size.height));
outRect.width = (nscoord)frame.size.width;
outRect.height = (nscoord)frame.size.height;
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event)
{
if (!menu || !widget || !event)
return NPERR_GENERIC_ERROR;
NSMenu* cocoaMenu = (NSMenu*)menu;
NSView* cocoaView = (NSView*)widget->GetNativeData(NS_NATIVE_WIDGET);
NSEventType cocoaEventType = NSRightMouseDown;
unsigned int cocoaModifierFlags = 0;
double x = 0.0; // Coordinates for the context menu in plugin terms, top-left origin.
double y = 0.0;
NPCocoaEventType eventType = event->type;
if (eventType == NPCocoaEventMouseDown ||
eventType == NPCocoaEventMouseUp ||
eventType == NPCocoaEventMouseMoved ||
eventType == NPCocoaEventMouseEntered ||
eventType == NPCocoaEventMouseExited ||
eventType == NPCocoaEventMouseDragged) {
cocoaEventType = event->data.mouse.buttonNumber;
cocoaModifierFlags = event->data.mouse.modifierFlags;
x = event->data.mouse.pluginX;
y = event->data.mouse.pluginY;
if ((x < 0.0) || (y < 0.0))
return NPERR_GENERIC_ERROR;
}
// Flip the coords to bottom-left origin.
NSRect viewFrame = [cocoaView frame];
double shiftedX = x;
double shiftedY = viewFrame.size.height - y;
// Shift to window coords.
shiftedX += viewFrame.origin.x;
shiftedY += [cocoaView convertPoint:NSMakePoint(0,0) toView:nil].y - viewFrame.size.height;
// Create an NSEvent we can use to show the context menu. Only the location
// is important here so just simulate a right mouse down. The coordinates
// must be in top-level window terms.
NSEvent* cocoaEvent = [NSEvent mouseEventWithType:cocoaEventType
location:NSMakePoint(shiftedX, shiftedY)
modifierFlags:cocoaModifierFlags
timestamp:0
windowNumber:[[cocoaView window] windowNumber]
context:nil
eventNumber:0
clickCount:1
pressure:0.0];
[NSMenu popUpContextMenu:cocoaMenu withEvent:cocoaEvent forView:cocoaView];
return NPERR_NO_ERROR;
}
NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace)
{
NS_ASSERTION(inView, "Must have a native view to convert coordinates.");
// Caller has to want a result.
if (!destX && !destY)
return PR_FALSE;
if (sourceSpace == destSpace) {
if (destX)
*destX = sourceX;
if (destY)
*destY = sourceY;
return PR_TRUE;
}
NSView* view = (NSView*)inView;
NSWindow* window = [view window];
NSPoint sourcePoint = NSMakePoint(sourceX, sourceY);
// Convert to screen space.
NSPoint screenPoint;
switch (sourceSpace) {
case NPCoordinateSpacePlugin:
screenPoint = [view convertPoint:sourcePoint toView:nil];
screenPoint = [window convertBaseToScreen:screenPoint];
break;
case NPCoordinateSpaceWindow:
screenPoint = [window convertBaseToScreen:sourcePoint];
break;
case NPCoordinateSpaceFlippedWindow:
sourcePoint.y = [window frame].size.height - sourcePoint.y;
screenPoint = [window convertBaseToScreen:sourcePoint];
break;
case NPCoordinateSpaceScreen:
screenPoint = sourcePoint;
break;
case NPCoordinateSpaceFlippedScreen:
sourcePoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - sourcePoint.y;
screenPoint = sourcePoint;
break;
default:
return PR_FALSE;
}
// Convert from screen to dest space.
NSPoint destPoint;
switch (destSpace) {
case NPCoordinateSpacePlugin:
destPoint = [window convertScreenToBase:screenPoint];
destPoint = [view convertPoint:destPoint fromView:nil];
break;
case NPCoordinateSpaceWindow:
destPoint = [window convertScreenToBase:screenPoint];
break;
case NPCoordinateSpaceFlippedWindow:
destPoint = [window convertScreenToBase:screenPoint];
destPoint.y = [window frame].size.height - destPoint.y;
break;
case NPCoordinateSpaceScreen:
destPoint = screenPoint;
break;
case NPCoordinateSpaceFlippedScreen:
destPoint = screenPoint;
destPoint.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - destPoint.y;
break;
default:
return PR_FALSE;
}
if (destX)
*destX = destPoint.x;
if (destY)
*destY = destPoint.y;
return PR_TRUE;
}

Просмотреть файл

@ -60,6 +60,8 @@
#ifdef XP_MACOSX
#ifdef __LP64__
#define NP_NO_QUICKDRAW
#define NP_NO_CARBON
#include <ApplicationServices/ApplicationServices.h>
#else
#include <Carbon/Carbon.h>
#endif
@ -78,7 +80,7 @@
/*----------------------------------------------------------------------*/
#define NP_VERSION_MAJOR 0
#define NP_VERSION_MINOR 22
#define NP_VERSION_MINOR 23
/* The OS/2 version of Netscape uses RC_DATA to define the
@ -246,6 +248,13 @@ typedef enum {
#endif
NPDrawingModelCoreGraphics = 1
} NPDrawingModel;
typedef enum {
#ifndef NP_NO_CARBON
NPEventModelCarbon = 0,
#endif
NPEventModelCocoa = 1
} NPEventModel;
#endif
/*
@ -325,6 +334,8 @@ typedef enum {
#ifdef XP_MACOSX
/* Used for negotiating drawing models */
, NPPVpluginDrawingModel = 1000
/* Used for negotiating event models */
, NPPVpluginEventModel = 1001
#endif
} NPPVariable;
@ -363,6 +374,10 @@ typedef enum {
, NPNVsupportsQuickDrawBool = 2000
#endif
, NPNVsupportsCoreGraphicsBool = 2001
#ifndef NP_NO_CARBON
, NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
#endif
, NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
#endif
} NPNVariable;
@ -430,9 +445,7 @@ typedef struct _NPPrint
} print;
} NPPrint;
#ifdef XP_MACOSX
typedef EventRecord NPEvent;
#elif defined(XP_WIN)
#if defined(XP_WIN)
typedef struct _NPEvent
{
uint16_t event;
@ -453,7 +466,6 @@ typedef void* NPEvent;
#endif /* XP_MACOSX */
#ifdef XP_MACOSX
typedef void* NPRegion;
#ifndef NP_NO_QUICKDRAW
typedef RgnHandle NPQDRegion;
@ -467,7 +479,26 @@ typedef Region NPRegion;
typedef void *NPRegion;
#endif
typedef struct _NPNSString NPNSString;
typedef struct _NPNSWindow NPNSWindow;
typedef struct _NPNSMenu NPNSMenu;
#ifdef XP_MACOSX
typedef NPNSMenu NPMenu;
#else
typedef void *NPMenu;
#endif
typedef enum {
NPCoordinateSpacePlugin = 1,
NPCoordinateSpaceWindow,
NPCoordinateSpaceFlippedWindow,
NPCoordinateSpaceScreen,
NPCoordinateSpaceFlippedScreen
} NPCoordinateSpace;
#ifdef XP_MACOSX
typedef struct NP_Port
{
CGrafPtr port;
@ -478,9 +509,68 @@ typedef struct NP_Port
typedef struct NP_CGContext
{
CGContextRef context;
WindowRef window;
#ifdef NP_NO_CARBON
NPNSWindow *window;
#else
void *window; /* A WindowRef or NULL for the Cocoa event model. */
#endif
} NP_CGContext;
typedef enum {
NPCocoaEventDrawRect = 1,
NPCocoaEventMouseDown,
NPCocoaEventMouseUp,
NPCocoaEventMouseMoved,
NPCocoaEventMouseEntered,
NPCocoaEventMouseExited,
NPCocoaEventMouseDragged,
NPCocoaEventKeyDown,
NPCocoaEventKeyUp,
NPCocoaEventFlagsChanged,
NPCocoaEventFocusChanged,
NPCocoaEventWindowFocusChanged,
NPCocoaEventScrollWheel,
NPCocoaEventTextInput
} NPCocoaEventType;
typedef struct _NPCocoaEvent {
NPCocoaEventType type;
uint32_t version;
union {
struct {
uint32_t modifierFlags;
double pluginX;
double pluginY;
int32_t buttonNumber;
int32_t clickCount;
double deltaX;
double deltaY;
double deltaZ;
} mouse;
struct {
uint32_t modifierFlags;
NPNSString *characters;
NPNSString *charactersIgnoringModifiers;
NPBool isARepeat;
uint16_t keyCode;
} key;
struct {
CGContextRef context;
double x;
double y;
double width;
double height;
} draw;
struct {
NPBool hasFocus;
} focus;
struct {
NPNSString *text;
} text;
} data;
} NPCocoaEvent;
#ifndef NP_NO_CARBON
/* Non-standard event types that can be passed to HandleEvent */
enum NPEventType {
NPEventType_GetFocusEvent = (osEvt + 16),
@ -491,12 +581,12 @@ enum NPEventType {
NPEventType_ScrollingBeginsEvent = 1000,
NPEventType_ScrollingEndsEvent
};
#ifdef OBSOLETE
#define getFocusEvent (osEvt + 16)
#define loseFocusEvent (osEvt + 17)
#define adjustCursorEvent (osEvt + 18)
#endif
#endif /* OBSOLETE */
#endif /* NP_NO_CARBON */
#endif /* XP_MACOSX */
@ -676,8 +766,10 @@ NPError NP_LOADDS NPN_GetAuthenticationInfo(NPP instance,
char **username, uint32_t *ulen,
char **password,
uint32_t *plen);
uint32_t NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
void NPN_UnscheduleTimer(NPP instance, uint32_t timerID);
uint32_t NP_LOADDS NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
void NP_LOADDS NPN_UnscheduleTimer(NPP instance, uint32_t timerID);
NPError NP_LOADDS NPN_PopUpContextMenu(NPP instance, NPMenu* menu);
NPBool NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
#ifdef __cplusplus
} /* end extern "C" */

Просмотреть файл

@ -118,6 +118,8 @@ typedef NPError (*NPN_SetValueForURLPtr)(NPP npp, NPNURLVariable variable,
typedef NPError (*NPN_GetAuthenticationInfoPtr)(NPP npp, const char *protocol, const char *host, int32_t port, const char *scheme, const char *realm, char **username, uint32_t *ulen, char **password, uint32_t *plen);
typedef uint32_t (*NPN_ScheduleTimerPtr)(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
typedef void (*NPN_UnscheduleTimerPtr)(NPP instance, uint32_t timerID);
typedef NPError (*NPN_PopUpContextMenuPtr)(NPP instance, NPMenu* menu);
typedef NPBool (*NPN_ConvertPointPtr)(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
typedef struct _NPPluginFuncs {
uint16_t size;
@ -191,6 +193,8 @@ typedef struct _NPNetscapeFuncs {
NPN_GetAuthenticationInfoPtr getauthenticationinfo;
NPN_ScheduleTimerPtr scheduletimer;
NPN_UnscheduleTimerPtr unscheduletimer;
NPN_PopUpContextMenuPtr popupcontextmenu;
NPN_ConvertPointPtr convertpoint;
} NPNetscapeFuncs;
#ifdef XP_MACOSX

Просмотреть файл

@ -42,9 +42,14 @@
interface nsIPluginInstance;
interface nsIDocument;
[ref] native nsIPluginInstanceRef(nsIPluginInstance *);
%{C++
#include "npapi.h"
class nsPluginEvent;
%}
[uuid(2e6cc23b-7d4e-4b0a-ad45-f2281c937f5c)]
[ref] native nsIPluginInstanceRef(nsIPluginInstance*);
[uuid(109BAD0E-7071-4907-B657-4507C834E448)]
interface nsIPluginInstanceOwner : nsISupports
{
/**
@ -66,7 +71,6 @@ interface nsIPluginInstanceOwner : nsISupports
/**
* Get the display mode for the plugin instance.
*/
//void getMode(nsPluginMode *aMode);
readonly attribute nsPluginMode mode;
/**
@ -87,23 +91,20 @@ interface nsIPluginInstanceOwner : nsISupports
void *aPostData, PRUint32 aPostDataLen,
void *aHeadersData, PRUint32 aHeadersDataLen,
PRBool aIsFile = PR_FALSE) = 0;
%}
/**
* Show a status message in the host environment.
*/
void showStatus(in string aStatusMsg);
%{C++
NS_IMETHOD
ShowStatus(const PRUnichar *aStatusMsg) = 0;
NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg) = 0;
%}
/**
* Get the associated document.
*/
//void getDocument(nsIDocument* *aDocument);
readonly attribute nsIDocument document;
/**
@ -125,4 +126,13 @@ interface nsIPluginInstanceOwner : nsISupports
* Get NetscapeWindow, corresponds to NPNVnetscapeWindow
*/
void getNetscapeWindow(in voidPtr aValue);
/**
* Show native context menu
*/
%{C++
virtual NPError ShowNativeContextMenu(NPMenu* menu, nsPluginEvent* event) = 0;
virtual NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace) = 0;
%}
};

Просмотреть файл

@ -201,6 +201,7 @@ enum nsPluginInstanceVariable {
nsPluginInstanceVariable_WantsAllNetworkStreams = 18
#ifdef XP_MACOSX
, nsPluginInstanceVariable_DrawingModel = 20
, nsPluginInstanceVariable_EventModel = 21
#endif
};
@ -230,7 +231,7 @@ enum nsPluginWindowType {
#ifdef XP_MACOSX
typedef WindowRef nsPluginPlatformWindowRef;
typedef void* nsPluginPlatformWindowRef;
#ifndef NP_NO_QUICKDRAW
struct nsPluginPortQD {
@ -244,7 +245,7 @@ typedef RgnHandle nsPluginRegionQD;
struct nsPluginPortCG {
CGContextRef context;
WindowRef window;
void* window;
};
typedef CGPathRef nsPluginRegionCG;
@ -319,8 +320,8 @@ struct nsPluginPrint {
struct nsPluginEvent {
#ifdef XP_MACOSX
EventRecord* event;
nsPluginPlatformWindowRef window;
void* event;
nsPluginPlatformWindowRef window;
#elif defined(XP_OS2)
uint32 event;

Просмотреть файл

@ -255,6 +255,8 @@ nsNPAPIPlugin::CheckClassInitialized(void)
CALLBACKS.getauthenticationinfo = ((NPN_GetAuthenticationInfoPtr)_getauthenticationinfo);
CALLBACKS.scheduletimer = ((NPN_ScheduleTimerPtr)_scheduletimer);
CALLBACKS.unscheduletimer = ((NPN_UnscheduleTimerPtr)_unscheduletimer);
CALLBACKS.popupcontextmenu = ((NPN_PopUpContextMenuPtr)_popupcontextmenu);
CALLBACKS.convertpoint = ((NPN_ConvertPointPtr)_convertpoint);
if (!sPluginThreadAsyncCallLock)
sPluginThreadAsyncCallLock = nsAutoLock::NewLock("sPluginThreadAsyncCallLock");
@ -1997,6 +1999,19 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
case NPNVsupportsCoreGraphicsBool: {
*(NPBool*)result = PR_TRUE;
return NPERR_NO_ERROR;
}
#ifndef NP_NO_CARBON
case NPNVsupportsCarbonBool: {
*(NPBool*)result = PR_TRUE;
return NPERR_NO_ERROR;
}
#endif
case NPNVsupportsCocoaBool: {
*(NPBool*)result = PR_TRUE;
return NPERR_NO_ERROR;
}
#endif
@ -2125,6 +2140,16 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
return NPERR_GENERIC_ERROR;
}
}
case NPPVpluginEventModel: {
if (inst) {
inst->SetEventModel((NPEventModel)NS_PTR_TO_INT32(result));
return NPERR_NO_ERROR;
}
else {
return NPERR_GENERIC_ERROR;
}
}
#endif
default:
@ -2535,6 +2560,26 @@ _unscheduletimer(NPP instance, uint32_t timerID)
inst->UnscheduleTimer(timerID);
}
NPError NP_CALLBACK
_popupcontextmenu(NPP instance, NPMenu* menu)
{
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
if (!inst)
return NPERR_GENERIC_ERROR;
return inst->PopUpContextMenu(menu);
}
NPBool NP_CALLBACK
_convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
{
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
if (!inst)
return PR_FALSE;
return inst->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
}
void
OnPluginDestroy(NPP instance)
{

Просмотреть файл

@ -216,6 +216,12 @@ _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)
void NP_CALLBACK
_unscheduletimer(NPP instance, uint32_t timerID);
NPError NP_CALLBACK
_popupcontextmenu(NPP instance, NPMenu* menu);
NPBool NP_CALLBACK
_convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
PR_END_EXTERN_C
const char *

Просмотреть файл

@ -876,6 +876,11 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
#else
mDrawingModel(NPDrawingModelQuickDraw),
#endif
#ifdef NP_NO_CARBON
mEventModel(NPEventModelCocoa),
#else
mEventModel(NPEventModelCarbon),
#endif
#endif
mWindowless(PR_FALSE),
mTransparent(PR_FALSE),
@ -885,7 +890,9 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
mInPluginInitCall(PR_FALSE),
mLibrary(aLibrary),
mStreams(nsnull),
mMIMEType(nsnull)
mMIMEType(nsnull),
mOwner(nsnull),
mCurrentPluginEvent(nsnull)
{
NS_ASSERTION(mCallbacks != NULL, "null callbacks");
@ -1204,20 +1211,27 @@ nsNPAPIPluginInstance::InitializePlugin()
NS_IMETHODIMP nsNPAPIPluginInstance::SetWindow(nsPluginWindow* window)
{
// XXX NPAPI plugins don't want a SetWindow(NULL).
// NPAPI plugins don't want a SetWindow(NULL).
if (!window || !mStarted)
return NS_OK;
NPError error;
#if defined (MOZ_WIDGET_GTK2)
#if defined(MOZ_WIDGET_GTK2)
// bug 108347, flash plugin on linux doesn't like window->width <=
// 0, but Java needs wants this call.
if (!nsPluginHost::IsJavaMIMEType(mMIMEType) && window->type == nsPluginWindowType_Window &&
(window->width <= 0 || window->height <= 0)) {
return NS_OK;
}
#endif // MOZ_WIDGET
#elif defined(XP_MACOSX)
// Under the Cocoa event model the context and the window in SetWindow calls
// should always be NULL. For now NULL them out here but in the future we can
// optimize to not set them in the first place and only make SetWindow calls
// when size or position changes.
if (GetEventModel() == NPEventModelCocoa) {
window->window->cgPort.context = NULL;
window->window->cgPort.window = NULL;
}
#endif
if (mCallbacks->setwindow) {
PluginDestructionGuard guard(this);
@ -1230,6 +1244,7 @@ NS_IMETHODIMP nsNPAPIPluginInstance::SetWindow(nsPluginWindow* window)
PRBool oldVal = mInPluginInitCall;
mInPluginInitCall = PR_TRUE;
NPError error;
NS_TRY_SAFE_CALL_RETURN(error, (*mCallbacks->setwindow)(&mNPP, (NPWindow*)window), mLibrary, this);
mInPluginInitCall = oldVal;
@ -1238,10 +1253,6 @@ NS_IMETHODIMP nsNPAPIPluginInstance::SetWindow(nsPluginWindow* window)
("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
this, window->x, window->y, window->width, window->height,
window->clipRect.top, window->clipRect.bottom, window->clipRect.left, window->clipRect.right, error));
// XXX In the old code, we'd just ignore any errors coming
// back from the plugin's SetWindow(). Is this the correct
// behavior?!?
}
return NS_OK;
}
@ -1351,27 +1362,27 @@ NS_IMETHODIMP nsNPAPIPluginInstance::HandleEvent(nsPluginEvent* event, PRBool* h
PRInt16 result = 0;
if (mCallbacks->event) {
mCurrentPluginEvent = event;
#ifdef XP_MACOSX
result = (*mCallbacks->event)(&mNPP, (void*)event->event);
#elif defined(XP_WIN) || defined(XP_OS2)
NPEvent npEvent;
npEvent.event = event->event;
npEvent.wParam = event->wParam;
npEvent.lParam = event->lParam;
NS_TRY_SAFE_CALL_RETURN(result, (*mCallbacks->event)(&mNPP, (void*)&npEvent), mLibrary, this);
NPEvent npEvent;
npEvent.event = event->event;
npEvent.wParam = event->wParam;
npEvent.lParam = event->lParam;
NS_TRY_SAFE_CALL_RETURN(result, (*mCallbacks->event)(&mNPP, (void*)&npEvent), mLibrary, this);
#else // MOZ_X11 or other
result = (*mCallbacks->event)(&mNPP, (void*)&event->event);
result = (*mCallbacks->event)(&mNPP, (void*)&event->event);
#endif
NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
("NPP HandleEvent called: this=%p, npp=%p, event=%d, return=%d\n",
this, &mNPP, event->event, result));
*handled = result;
}
*handled = result;
mCurrentPluginEvent = nsnull;
}
return NS_OK;
}
@ -1409,13 +1420,17 @@ NS_IMETHODIMP nsNPAPIPluginInstance::GetValue(nsPluginInstanceVariable variable,
break;
case nsPluginInstanceVariable_CallSetWindowAfterDestroyBool:
*(PRBool *)value = 0; // not supported for 4.x plugins
*(PRBool *)value = 0; // not supported for NPAPI plugins
break;
#ifdef XP_MACOSX
case nsPluginInstanceVariable_DrawingModel:
*(NPDrawingModel*)value = mDrawingModel;
break;
case nsPluginInstanceVariable_EventModel:
*(NPEventModel*)value = mEventModel;
break;
#endif
default:
@ -1473,6 +1488,16 @@ NPDrawingModel nsNPAPIPluginInstance::GetDrawingModel()
{
return mDrawingModel;
}
void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel)
{
mEventModel = aModel;
}
NPEventModel nsNPAPIPluginInstance::GetEventModel()
{
return mEventModel;
}
#endif
NS_IMETHODIMP
@ -1729,6 +1754,27 @@ nsNPAPIPluginInstance::UnscheduleTimer(uint32_t timerID)
delete t;
}
// Show the context menu at the location for the current event.
// This can only be called from within an NPP_SendEvent call.
NPError
nsNPAPIPluginInstance::PopUpContextMenu(NPMenu* menu)
{
if (mOwner && mCurrentPluginEvent)
return mOwner->ShowNativeContextMenu(menu, mCurrentPluginEvent);
return NPERR_GENERIC_ERROR;
}
NPBool
nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace)
{
if (mOwner)
return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
return PR_FALSE;
}
nsresult
nsNPAPIPluginInstance::GetDOMElement(nsIDOMElement* *result)
{

Просмотреть файл

@ -93,6 +93,8 @@ public:
#ifdef XP_MACOSX
void SetDrawingModel(NPDrawingModel aModel);
NPDrawingModel GetDrawingModel();
void SetEventModel(NPEventModel aModel);
NPEventModel GetEventModel();
#endif
nsresult NewNotifyStream(nsIPluginStreamListener** listener,
@ -120,6 +122,8 @@ public:
nsNPAPITimer* TimerWithID(uint32_t id, PRUint32* index);
uint32_t ScheduleTimer(uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
void UnscheduleTimer(uint32_t timerID);
NPError PopUpContextMenu(NPMenu* menu);
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
protected:
nsresult InitializePlugin();
@ -144,6 +148,7 @@ protected:
#ifdef XP_MACOSX
NPDrawingModel mDrawingModel;
NPEventModel mEventModel;
#endif
// these are used to store the windowless properties
@ -170,6 +175,9 @@ private:
nsIPluginInstanceOwner *mOwner;
nsTArray<nsNPAPITimer*> mTimers;
// non-null during a HandleEvent call
nsPluginEvent* mCurrentPluginEvent;
};
#endif // nsNPAPIPluginInstance_h_

Просмотреть файл

@ -49,7 +49,8 @@ NPError NP_Initialize(NPNetscapeFuncs *browserFuncs);
NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs);
void NP_Shutdown(void);
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode,
int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
NPError NPP_Destroy(NPP instance, NPSavedData** save);
NPError NPP_SetWindow(NPP instance, NPWindow* window);
NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);
@ -74,7 +75,7 @@ typedef struct PluginInstance {
NPWindow window;
} PluginInstance;
void drawPlugin(NPP instance);
void drawPlugin(NPP instance, NPCocoaEvent* event);
// Symbol called once by the browser to initialize the plugin
NPError NP_Initialize(NPNetscapeFuncs* browserFuncs)
@ -114,23 +115,35 @@ void NP_Shutdown(void)
}
// Called to create a new instance of the plugin
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved)
NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode,
int16_t argc, char* argn[], char* argv[], NPSavedData* saved)
{
PluginInstance *newInstance = (PluginInstance*)malloc(sizeof(PluginInstance));
bzero(newInstance, sizeof(PluginInstance));
newInstance->npp = instance;
instance->pdata = newInstance;
NPBool supportsCoreGraphics;
if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR)
supportsCoreGraphics = FALSE;
if (!supportsCoreGraphics)
// select the right drawing model if necessary
NPBool supportsCoreGraphics = false;
if ((browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR) &&
supportsCoreGraphics) {
browser->setvalue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics);
} else {
printf("CoreGraphics drawing model not supported, can't create a plugin instance.\n");
return NPERR_INCOMPATIBLE_VERSION_ERROR;
browser->setvalue(instance, NPPVpluginDrawingModel, (void *)NPDrawingModelCoreGraphics);
}
// select the Cocoa event model
NPBool supportsCocoaEvents = false;
if ((browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoaEvents) == NPERR_NO_ERROR) &&
supportsCocoaEvents) {
browser->setvalue(instance, NPPVpluginEventModel, (void*)NPEventModelCocoa);
} else {
printf("Cocoa event model not supported, can't create a plugin instance.\n");
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
return NPERR_NO_ERROR;
}
@ -186,10 +199,12 @@ void NPP_Print(NPP instance, NPPrint* platformPrint)
int16_t NPP_HandleEvent(NPP instance, void* event)
{
EventRecord* carbonEvent = (EventRecord*)event;
if (carbonEvent && (carbonEvent->what == updateEvt))
drawPlugin(instance);
NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event;
if (cocoaEvent && (cocoaEvent->type == NPCocoaEventDrawRect)) {
drawPlugin(instance, (NPCocoaEvent*)event);
return 1;
}
return 0;
}
@ -208,10 +223,12 @@ NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
return NPERR_GENERIC_ERROR;
}
void drawPlugin(NPP instance)
void drawPlugin(NPP instance, NPCocoaEvent* event)
{
PluginInstance* currentInstance = (PluginInstance*)(instance->pdata);
CGContextRef cgContext = ((NP_CGContext*)(currentInstance->window.window))->context;
CGContextRef cgContext = event->data.draw.context;
if (cgContext)
return;
float windowWidth = currentInstance->window.width;
float windowHeight = currentInstance->window.height;
@ -233,11 +250,15 @@ void drawPlugin(NPP instance)
CFURLRef imageURL = ::CFBundleCopyResourceURL(bundle, CFSTR("plugin"), CFSTR("png"), NULL);
CGDataProviderRef dataProvider = ::CGDataProviderCreateWithURL(imageURL);
::CFRelease(imageURL);
CGImageRef imageRef = ::CGImageCreateWithPNGDataProvider(dataProvider, NULL, TRUE, kCGRenderingIntentDefault);
CGImageRef imageRef = ::CGImageCreateWithPNGDataProvider(dataProvider, NULL, TRUE,
kCGRenderingIntentDefault);
::CGDataProviderRelease(dataProvider);
float imageWidth = ::CGImageGetWidth(imageRef);
float imageHeight = ::CGImageGetHeight(imageRef);
CGRect drawRect = ::CGRectMake(windowWidth / 2 - imageWidth / 2, windowHeight / 2 - imageHeight / 2, imageWidth, imageHeight);
CGRect drawRect = ::CGRectMake(windowWidth / 2 - imageWidth / 2,
windowHeight / 2 - imageHeight / 2,
imageWidth,
imageHeight);
::CGContextDrawImage(cgContext, drawRect, imageRef);
::CGImageRelease(imageRef);

Просмотреть файл

@ -28,7 +28,7 @@ typedef struct PluginInstance {
NPWindow window;
} PluginInstance;
void drawPlugin(NPP instance);
void drawPlugin(NPP instance, NPCocoaEvent* event);
// Symbol called once by the browser to initialize the plugin
NPError NP_Initialize(NPNetscapeFuncs* browserFuncs)
@ -77,14 +77,23 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc
newInstance->npp = instance;
instance->pdata = newInstance;
NPBool supportsCoreGraphics;
if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR)
supportsCoreGraphics = FALSE;
if (!supportsCoreGraphics)
// select the right drawing model if necessary
NPBool supportsCoreGraphics = false;
if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR && supportsCoreGraphics) {
browser->setvalue(instance, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics);
} else {
printf("CoreGraphics drawing model not supported, can't create a plugin instance.\n");
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
browser->setvalue(instance, NPPVpluginDrawingModel, (void *)NPDrawingModelCoreGraphics);
// select the Cocoa event model
NPBool supportsCocoaEvents = false;
if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoaEvents) == NPERR_NO_ERROR && supportsCocoaEvents) {
browser->setvalue(instance, NPPVpluginEventModel, (void*)NPEventModelCocoa);
} else {
printf("Cocoa event model not supported, can't create a plugin instance.\n");
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
if (!browserUAString) {
const char* ua = browser->uagent(instance);
@ -146,9 +155,11 @@ void NPP_Print(NPP instance, NPPrint* platformPrint)
int16_t NPP_HandleEvent(NPP instance, void* event)
{
EventRecord* carbonEvent = (EventRecord*)event;
if (carbonEvent && (carbonEvent->what == updateEvt))
drawPlugin(instance);
NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event;
if (cocoaEvent && (cocoaEvent->type == NPCocoaEventDrawRect)) {
drawPlugin(instance, (NPCocoaEvent*)event);
return 1;
}
return 0;
}
@ -168,14 +179,16 @@ NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
return NPERR_GENERIC_ERROR;
}
void drawPlugin(NPP instance)
void drawPlugin(NPP instance, NPCocoaEvent* event)
{
if (!browserUAString)
return;
PluginInstance* currentInstance = (PluginInstance*)(instance->pdata);
CGContextRef cgContext = ((NP_CGContext*)(currentInstance->window.window))->context;
CGContextRef cgContext = event->data.draw.context;
if (!cgContext)
return;
float windowWidth = currentInstance->window.width;
float windowHeight = currentInstance->window.height;

Просмотреть файл

@ -34,6 +34,11 @@
#include "nptest_platform.h"
#include <CoreServices/CoreServices.h>
#ifdef __LP64__
// 64-bit requires the Cocoa event model
#define USE_COCOA_NPAPI 1
#endif
bool
pluginSupportsWindowMode()
{
@ -50,14 +55,27 @@ NPError
pluginInstanceInit(InstanceData* instanceData)
{
NPP npp = instanceData->npp;
// select the right drawing model if necessary
NPBool supportsCoreGraphics = false;
if (NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR && supportsCoreGraphics) {
if ((NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) == NPERR_NO_ERROR) &&
supportsCoreGraphics) {
NPN_SetValue(npp, NPPVpluginDrawingModel, (void*)NPDrawingModelCoreGraphics);
} else {
printf("CoreGraphics drawing model not supported, can't create a plugin instance.\n");
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
#ifdef USE_COCOA_NPAPI
NPBool supportsCocoaEvents = false;
if ((NPN_GetValue(npp, NPNVsupportsCocoaBool, &supportsCocoaEvents) == NPERR_NO_ERROR) &&
supportsCocoaEvents) {
NPN_SetValue(npp, NPPVpluginEventModel, (void*)NPEventModelCocoa);
} else {
printf("Cocoa event model not supported, can't create a plugin instance.\n");
return NPERR_INCOMPATIBLE_VERSION_ERROR;
}
#endif
return NPERR_NO_ERROR;
}
@ -106,7 +124,11 @@ GetColorsFromRGBA(PRUint32 rgba, float* r, float* g, float* b, float* a)
}
static void
#ifdef USE_COCOA_NPAPI
pluginDraw(InstanceData* instanceData, NPCocoaEvent* event)
#else
pluginDraw(InstanceData* instanceData)
#endif
{
if (!instanceData)
return;
@ -120,7 +142,12 @@ pluginDraw(InstanceData* instanceData)
return;
NPWindow window = instanceData->window;
#ifdef USE_COCOA_NPAPI
CGContextRef cgContext = event->data.draw.context;
#else
CGContextRef cgContext = ((NP_CGContext*)(window.window))->context;
#endif
float windowWidth = window.width;
float windowHeight = window.height;
@ -146,7 +173,35 @@ pluginDraw(InstanceData* instanceData)
CGContextSetLineWidth(cgContext, 6.0);
CGContextStrokePath(cgContext);
// draw the UA string using ATSUI
#ifdef USE_COCOA_NPAPI // draw the UA string using Core Text
CGContextSetTextMatrix(cgContext, CGAffineTransformIdentity);
// Initialize a rectangular path.
CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds = CGRectMake(10.0, 10.0, windowWidth - 20.0, windowHeight - 20.0);
CGPathAddRect(path, NULL, bounds);
// Initialize an attributed string.
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
CFAttributedStringReplaceString(attrString, CFRangeMake(0, 0), uaCFString);
// Create a color and add it as an attribute to the string.
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = { 0.0, 0.0, 0.0, 1.0 };
CGColorRef red = CGColorCreate(rgbColorSpace, components);
CGColorSpaceRelease(rgbColorSpace);
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, 50), kCTForegroundColorAttributeName, red);
// Create the framesetter with the attributed string.
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
CFRelease(attrString);
// Create the frame and draw it into the graphics context
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CFRelease(framesetter);
CTFrameDraw(frame, cgContext);
CFRelease(frame);
#else // draw the UA string using ATSUI
CGContextSetGrayFillColor(cgContext, 0.0, 1.0);
ATSUStyle atsuStyle;
ATSUCreateStyle(&atsuStyle);
@ -199,13 +254,16 @@ pluginDraw(InstanceData* instanceData)
UniCharArrayOffset currentDrawOffset = kATSUFromTextBeginning;
unsigned int i = 0;
while (i < softBreakCount) {
ATSUDrawText(atsuLayout, currentDrawOffset, softBreaks[i], FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
ATSUDrawText(atsuLayout, currentDrawOffset, softBreaks[i], FloatToFixed(5.0),
FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
currentDrawOffset = softBreaks[i];
i++;
}
ATSUDrawText(atsuLayout, currentDrawOffset, kATSUToTextEnd, FloatToFixed(5.0), FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
ATSUDrawText(atsuLayout, currentDrawOffset, kATSUToTextEnd, FloatToFixed(5.0),
FloatToFixed(windowHeight - 5.0 - (lineHeight * (i + 1.0))));
free(unicharBuffer);
free(softBreaks);
#endif
// restore the cgcontext gstate
CGContextRestoreGState(cgContext);
@ -236,6 +294,25 @@ pluginDraw(InstanceData* instanceData)
int16_t
pluginHandleEvent(InstanceData* instanceData, void* event)
{
#ifdef USE_COCOA_NPAPI
NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)event;
if (!cocoaEvent)
return 0;
switch (cocoaEvent->type) {
case NPCocoaEventDrawRect:
pluginDraw(instanceData, cocoaEvent);
return 1;
case NPCocoaEventMouseDown:
case NPCocoaEventMouseUp:
case NPCocoaEventMouseMoved:
instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX;
instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY;
return 1;
default:
return 0;
}
#else
EventRecord* carbonEvent = (EventRecord*)event;
if (!carbonEvent)
return 0;
@ -254,6 +331,7 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
default:
return 0;
}
#endif
}
int32_t pluginGetEdge(InstanceData* instanceData, RectEdge edge)

Просмотреть файл

@ -38,11 +38,11 @@
#include "nsISupports.h"
/* starting interface: nsIPluginWidget */
#define NS_IPLUGINWIDGET_IID_STR "d530ce43-8f6e-45c5-a984-35c43da19073"
#define NS_IPLUGINWIDGET_IID_STR "034E8A7E-BE36-4039-B229-39C41E9D4CD2"
#define NS_IPLUGINWIDGET_IID \
{0xd530ce43, 0x8f6e, 0x45c5, \
{ 0xa9, 0x84, 0x35, 0xc4, 0x3d, 0xa1, 0x90, 0x73 }}
#define NS_IPLUGINWIDGET_IID \
{ 0x034E8A7E, 0xBE36, 0x4039, \
{ 0xB2, 0x29, 0x39, 0xC4, 0x1E, 0x9D, 0x4C, 0xD2 } }
struct nsIntPoint;
class nsIPluginInstanceOwner;
@ -60,6 +60,10 @@ class NS_NO_VTABLE nsIPluginWidget : public nsISupports
NS_IMETHOD EndDrawPlugin(void) = 0;
NS_IMETHOD SetPluginInstanceOwner(nsIPluginInstanceOwner* pluginInstanceOwner) = 0;
NS_IMETHOD SetPluginEventModel(int inEventModel) = 0;
NS_IMETHOD GetPluginEventModel(int* outEventModel) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIPluginWidget, NS_IPLUGINWIDGET_IID)

Просмотреть файл

@ -128,9 +128,9 @@ enum {
// the nsChildView that created the view. It retains this NSView, so
// the link back to it must be weak.
nsChildView* mGeckoChild;
// Whether we're a plugin view.
BOOL mIsPluginView;
BOOL mSendCarbonPluginEvents; // true if we should send carbon events to plugins
// The following variables are only valid during key down event processing.
// Their current usage needs to be fixed to avoid problems with nested event
@ -385,7 +385,10 @@ public:
NS_IMETHOD StartDrawPlugin();
NS_IMETHOD EndDrawPlugin();
NS_IMETHOD SetPluginInstanceOwner(nsIPluginInstanceOwner* aInstanceOwner);
NS_IMETHOD SetPluginEventModel(int inEventModel);
NS_IMETHOD GetPluginEventModel(int* outEventModel);
virtual nsTransparencyMode GetTransparencyMode();
virtual void SetTransparencyMode(nsTransparencyMode aMode);

Просмотреть файл

@ -179,6 +179,8 @@ PRUint32 nsChildView::sLastInputEventCount = 0;
- (void)setIsPluginView:(BOOL)aIsPlugin;
- (BOOL)isPluginView;
- (void)setSendCarbonPluginEvents:(BOOL)sendCarbonEvents;
- (BOOL)shouldSendCarbonPluginEvents;
- (BOOL)childViewHasPlugin;
@ -349,6 +351,12 @@ FlipCocoaScreenCoordinate(NSPoint &inPoint)
inPoint.y = nsCocoaUtils::FlippedScreenY(inPoint.y);
}
static void
InitNPCocoaEvent(NPCocoaEvent* event)
{
memset(event, 0, sizeof(NPCocoaEvent));
}
static PRUint32
UnderlineAttributeToTextRangeType(PRUint32 aUnderlineStyle, NSRange selRange)
{
@ -882,30 +890,36 @@ void nsChildView::UpdatePluginPort()
{
NS_ASSERTION(mIsPluginView, "UpdatePluginPort called on non-plugin view");
NSWindow* window = [mView nativeWindow];
WindowRef topLevelWindow = window ? (WindowRef)[window windowRef] : nil;
NSWindow* cocoaWindow = [mView nativeWindow];
WindowRef carbonWindow = cocoaWindow ? (WindowRef)[cocoaWindow windowRef] : NULL;
if (mPluginIsCG) {
if (topLevelWindow) {
// [NSGraphicsContext currentContext] is supposed to "return the
// current graphics context of the current thread." But sometimes
// (when called while mView isn't focused for drawing) it returns a
// graphics context for the wrong window. [window graphicsContext]
// (which "provides the graphics context associated with the window
// for the current thread") seems always to return the "right"
// graphics context. See bug 500130.
mPluginPort.cgPort.context = (CGContextRef)
[[window graphicsContext] graphicsPort];
mPluginPort.cgPort.window = topLevelWindow;
// [NSGraphicsContext currentContext] is supposed to "return the
// current graphics context of the current thread." But sometimes
// (when called while mView isn't focused for drawing) it returns a
// graphics context for the wrong window. [window graphicsContext]
// (which "provides the graphics context associated with the window
// for the current thread") seems always to return the "right"
// graphics context. See bug 500130.
mPluginPort.cgPort.context = NULL;
mPluginPort.cgPort.window = NULL;
if ([(ChildView*)mView shouldSendCarbonPluginEvents]) {
if (carbonWindow) {
mPluginPort.cgPort.context = (CGContextRef)[[cocoaWindow graphicsContext] graphicsPort];
mPluginPort.cgPort.window = carbonWindow;
}
} else {
mPluginPort.cgPort.context = nil;
mPluginPort.cgPort.window = nil;
if (cocoaWindow) {
mPluginPort.cgPort.context = (CGContextRef)[[cocoaWindow graphicsContext] graphicsPort];
mPluginPort.cgPort.window = cocoaWindow;
}
}
} else {
if (topLevelWindow) {
mPluginPort.qdPort.port = ::GetWindowPort(topLevelWindow);
if (carbonWindow) {
mPluginPort.qdPort.port = ::GetWindowPort(carbonWindow);
NSPoint viewOrigin = [mView convertPoint:NSZeroPoint toView:nil];
NSRect frame = [[window contentView] frame];
NSRect frame = [[cocoaWindow contentView] frame];
viewOrigin.y = frame.size.height - viewOrigin.y;
// need to convert view's origin to window coordinates.
@ -913,7 +927,7 @@ void nsChildView::UpdatePluginPort()
mPluginPort.qdPort.portx = (PRInt32)-viewOrigin.x;
mPluginPort.qdPort.porty = (PRInt32)-viewOrigin.y;
} else {
mPluginPort.qdPort.port = nil;
mPluginPort.qdPort.port = NULL;
}
}
}
@ -1272,17 +1286,23 @@ NS_IMETHODIMP nsChildView::StartDrawPlugin()
NS_ASSERTION(mIsPluginView, "StartDrawPlugin must only be called on a plugin widget");
if (!mIsPluginView) return NS_ERROR_FAILURE;
// Prevent reentrant "drawing" (or in fact reentrant handling of any plugin
// event). Doing this for both CoreGraphics and QuickDraw plugins restores
// the 1.8-branch behavior wrt reentrancy, and fixes (or works around) bugs
// caused by plugins depending on the old behavior -- e.g. bmo bug 409615.
if (mPluginDrawing)
return NS_ERROR_FAILURE;
NSWindow* window = [mView nativeWindow];
if (!window)
return NS_ERROR_FAILURE;
// In QuickDraw drawing mode, prevent reentrant handling of any plugin event
// (this emulates behavior on the 1.8 branch, where only QuickDraw mode is
// supported). But in CoreGraphics drawing mode only do this if the current
// plugin event isn't an update/paint event. This allows popupcontextmenu()
// to work properly from a plugin that supports the Cocoa event model,
// without regressing bug 409615. See bug 435041. (StartDrawPlugin() and
// EndDrawPlugin() wrap every call to nsIPluginInstance::HandleEvent() --
// not just calls that "draw" or paint.)
if (!mPluginIsCG || (mView != [NSView focusView])) {
if (mPluginDrawing)
return NS_ERROR_FAILURE;
}
// It appears that the WindowRef from which we get the plugin port undergoes the
// traditional BeginUpdate/EndUpdate cycle, which, if you recall, sets the visible
// region to the intersection of the visible region and the update region. Since
@ -1353,6 +1373,18 @@ NS_IMETHODIMP nsChildView::SetPluginInstanceOwner(nsIPluginInstanceOwner* aInsta
return NS_OK;
}
NS_IMETHODIMP nsChildView::SetPluginEventModel(int inEventModel)
{
[(ChildView*)mView setSendCarbonPluginEvents:(inEventModel != NPEventModelCocoa)];
return NS_OK;
}
NS_IMETHODIMP nsChildView::GetPluginEventModel(int* outEventModel)
{
*outEventModel = ([(ChildView*)mView shouldSendCarbonPluginEvents] ? NPEventModelCarbon : NPEventModelCocoa);
return NS_OK;
}
void nsChildView::LiveResizeStarted()
{
// XXX todo. Use this to disable Java async redraw during resize
@ -2139,6 +2171,7 @@ NSEvent* gLastDragEvent = nil;
mWindow = nil;
mGeckoChild = inChild;
mIsPluginView = NO;
mSendCarbonPluginEvents = YES;
mCurKeyEvent = nil;
mKeyDownHandled = PR_FALSE;
@ -2344,6 +2377,16 @@ NSEvent* gLastDragEvent = nil;
return mIsPluginView;
}
- (void)setSendCarbonPluginEvents:(BOOL)sendCarbonEvents
{
mSendCarbonPluginEvents = sendCarbonEvents;
}
- (BOOL)shouldSendCarbonPluginEvents
{
return mSendCarbonPluginEvents;
}
- (BOOL)childViewHasPlugin
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
@ -3067,22 +3110,43 @@ static const PRInt32 sShadowInvalidationInterval = 100;
if (!mGeckoChild)
return;
NSUInteger modifierFlags = nsCocoaUtils::GetCocoaEventModifierFlags(theEvent);
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_BUTTON_DOWN, nsnull, nsMouseEvent::eReal);
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
geckoEvent.clickCount = [theEvent clickCount];
if (nsCocoaUtils::GetCocoaEventModifierFlags(theEvent) & NSControlKeyMask)
if (modifierFlags & NSControlKeyMask)
geckoEvent.button = nsMouseEvent::eRightButton;
else
geckoEvent.button = nsMouseEvent::eLeftButton;
// create native EventRecord for use by plugins
EventRecord macEvent;
macEvent.what = mouseDown;
macEvent.message = 0;
macEvent.when = ::TickCount();
::GetGlobalMouse(&macEvent.where);
macEvent.modifiers = ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &macEvent;
// Create event for use by plugins.
// This is going to our child view so we don't need to look up the destination
// event type.
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
carbonEvent.what = mouseDown;
carbonEvent.message = 0;
carbonEvent.when = ::TickCount();
::GetGlobalMouse(&carbonEvent.where);
carbonEvent.modifiers = ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &carbonEvent;
}
else {
InitNPCocoaEvent(&cocoaEvent);
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
cocoaEvent.type = NPCocoaEventMouseDown;
cocoaEvent.data.mouse.modifierFlags = modifierFlags;
cocoaEvent.data.mouse.pluginX = point.x;
cocoaEvent.data.mouse.pluginY = point.y;
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
geckoEvent.nativeMsg = &cocoaEvent;
}
mGeckoChild->DispatchWindowEvent(geckoEvent);
@ -3108,14 +3172,33 @@ static const PRInt32 sShadowInvalidationInterval = 100;
else
geckoEvent.button = nsMouseEvent::eLeftButton;
// create native EventRecord for use by plugins
EventRecord macEvent;
macEvent.what = mouseUp;
macEvent.message = 0;
macEvent.when = ::TickCount();
::GetGlobalMouse(&macEvent.where);
macEvent.modifiers = ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &macEvent;
// Create event for use by plugins.
// This is going to our child view so we don't need to look up the destination
// event type.
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
carbonEvent.what = mouseUp;
carbonEvent.message = 0;
carbonEvent.when = ::TickCount();
::GetGlobalMouse(&carbonEvent.where);
carbonEvent.modifiers = ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &carbonEvent;
}
else {
InitNPCocoaEvent(&cocoaEvent);
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
cocoaEvent.type = NPCocoaEventMouseUp;
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
cocoaEvent.data.mouse.pluginX = point.x;
cocoaEvent.data.mouse.pluginY = point.y;
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
geckoEvent.nativeMsg = &cocoaEvent;
}
mGeckoChild->DispatchWindowEvent(geckoEvent);
@ -3128,7 +3211,12 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
nsIWidget *widget,
nsMouseEvent::reasonType aReason,
NSPoint* localEventLocation,
nsMouseEvent::exitType type)
nsMouseEvent::exitType type,
unsigned int modifierFlags,
int buttonNumber,
float deltaX,
float deltaY,
float deltaZ)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
@ -3139,13 +3227,36 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
event.refPoint.x = nscoord((PRInt32)localEventLocation->x);
event.refPoint.y = nscoord((PRInt32)localEventLocation->y);
EventRecord macEvent;
macEvent.what = NPEventType_AdjustCursorEvent;
macEvent.message = 0;
macEvent.when = ::TickCount();
::GetGlobalMouse(&macEvent.where);
macEvent.modifiers = ::GetCurrentEventKeyModifiers();
event.nativeMsg = &macEvent;
// Create event for use by plugins.
// We need to know the plugin event model for the target widget.
nsCOMPtr<nsIPluginWidget> pluginWidget = do_QueryInterface(widget);
if (!pluginWidget)
return nsEventStatus_eIgnore;
int eventModel;
pluginWidget->GetPluginEventModel(&eventModel);
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (static_cast<NPEventModel>(eventModel) == NPEventModelCarbon) {
carbonEvent.what = NPEventType_AdjustCursorEvent;
carbonEvent.message = 0;
carbonEvent.when = ::TickCount();
::GetGlobalMouse(&carbonEvent.where);
carbonEvent.modifiers = ::GetCurrentEventKeyModifiers();
event.nativeMsg = &carbonEvent;
}
else {
InitNPCocoaEvent(&cocoaEvent);
cocoaEvent.type = ((msg == NS_MOUSE_ENTER) ? NPCocoaEventMouseEntered : NPCocoaEventMouseExited);
cocoaEvent.data.mouse.modifierFlags = modifierFlags;
cocoaEvent.data.mouse.pluginX = 5;
cocoaEvent.data.mouse.pluginY = 5;
cocoaEvent.data.mouse.buttonNumber = buttonNumber;
cocoaEvent.data.mouse.deltaX = deltaX;
cocoaEvent.data.mouse.deltaY = deltaY;
cocoaEvent.data.mouse.deltaZ = deltaZ;
event.nativeMsg = &cocoaEvent;
}
event.exit = type;
@ -3201,7 +3312,9 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
nsIWidget* lastViewEnteredWidget = [(NSView<mozView>*)sLastViewEntered widget];
NSPoint exitEventLocation = [sLastViewEntered convertPoint:windowEventLocation fromView:nil];
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal,
&exitEventLocation, nsMouseEvent::eTopLevel);
&exitEventLocation, nsMouseEvent::eTopLevel,
[theEvent modifierFlags], [theEvent buttonNumber], [theEvent deltaX],
[theEvent deltaY], [theEvent deltaZ]);
sLastViewEntered = nil;
}
return;
@ -3226,7 +3339,9 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
// NSLog(@"sending NS_MOUSE_EXIT event with point %f,%f\n", exitEventLocation.x, exitEventLocation.y);
nsIWidget* lastViewEnteredWidget = [(NSView<mozView>*)sLastViewEntered widget];
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal,
&exitEventLocation, nsMouseEvent::eTopLevel);
&exitEventLocation, nsMouseEvent::eTopLevel,
[theEvent modifierFlags], [theEvent buttonNumber], [theEvent deltaX],
[theEvent deltaY], [theEvent deltaZ]);
sLastViewEntered = nil;
}
return;
@ -3244,7 +3359,9 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
// NSLog(@"sending NS_MOUSE_EXIT event with point %f,%f\n", exitEventLocation.x, exitEventLocation.y);
nsIWidget* lastViewEnteredWidget = [(NSView<mozView>*)sLastViewEntered widget];
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_EXIT, lastViewEnteredWidget, nsMouseEvent::eReal,
&exitEventLocation, nsMouseEvent::eChild);
&exitEventLocation, nsMouseEvent::eChild,
[theEvent modifierFlags], [theEvent buttonNumber], [theEvent deltaX],
[theEvent deltaY], [theEvent deltaZ]);
// The mouse exit event we just sent may have destroyed this widget, bail if that happened.
if (!mGeckoChild)
@ -3253,7 +3370,9 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
// NSLog(@"sending NS_MOUSE_ENTER event with point %f,%f\n", viewEventLocation.x, viewEventLocation.y);
SendGeckoMouseEnterOrExitEvent(PR_TRUE, NS_MOUSE_ENTER, mGeckoChild, nsMouseEvent::eReal,
&viewEventLocation, nsMouseEvent::eChild);
&viewEventLocation, nsMouseEvent::eChild,
[theEvent modifierFlags], [theEvent buttonNumber], [theEvent deltaX],
[theEvent deltaY], [theEvent deltaZ]);
// The mouse enter event we just sent may have destroyed this widget, bail if that happened.
if (!mGeckoChild)
@ -3266,14 +3385,33 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_MOVE, nsnull, nsMouseEvent::eReal);
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
// create native EventRecord for use by plugins
EventRecord macEvent;
macEvent.what = NPEventType_AdjustCursorEvent;
macEvent.message = 0;
macEvent.when = ::TickCount();
::GetGlobalMouse(&macEvent.where);
macEvent.modifiers = ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &macEvent;
// Create event for use by plugins.
// This is going to our child view so we don't need to look up the destination
// event type.
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
carbonEvent.what = NPEventType_AdjustCursorEvent;
carbonEvent.message = 0;
carbonEvent.when = ::TickCount();
::GetGlobalMouse(&carbonEvent.where);
carbonEvent.modifiers = ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &carbonEvent;
}
else {
InitNPCocoaEvent(&cocoaEvent);
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
cocoaEvent.type = NPCocoaEventMouseMoved;
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
cocoaEvent.data.mouse.pluginX = point.x;
cocoaEvent.data.mouse.pluginY = point.y;
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
geckoEvent.nativeMsg = &cocoaEvent;
}
mGeckoChild->DispatchWindowEvent(geckoEvent);
@ -3296,14 +3434,31 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
nsMouseEvent geckoEvent(PR_TRUE, NS_MOUSE_MOVE, nsnull, nsMouseEvent::eReal);
[self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent];
// create native EventRecord for use by plugins
EventRecord macEvent;
macEvent.what = nullEvent;
macEvent.message = 0;
macEvent.when = ::TickCount();
::GetGlobalMouse(&macEvent.where);
macEvent.modifiers = btnState | ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &macEvent;
// create event for use by plugins
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
carbonEvent.what = nullEvent;
carbonEvent.message = 0;
carbonEvent.when = ::TickCount();
::GetGlobalMouse(&carbonEvent.where);
carbonEvent.modifiers = btnState | ::GetCurrentEventKeyModifiers();
geckoEvent.nativeMsg = &carbonEvent;
}
else {
InitNPCocoaEvent(&cocoaEvent);
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
cocoaEvent.type = NPCocoaEventMouseDragged;
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
cocoaEvent.data.mouse.pluginX = point.x;
cocoaEvent.data.mouse.pluginY = point.y;
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
geckoEvent.nativeMsg = &cocoaEvent;
}
mGeckoChild->DispatchWindowEvent(geckoEvent);
@ -3336,14 +3491,31 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
geckoEvent.button = nsMouseEvent::eRightButton;
geckoEvent.clickCount = [theEvent clickCount];
// create native EventRecord for use by plugins
EventRecord macEvent;
macEvent.what = mouseDown;
macEvent.message = 0;
macEvent.when = ::TickCount();
::GetGlobalMouse(&macEvent.where);
macEvent.modifiers = controlKey; // fake a context menu click
geckoEvent.nativeMsg = &macEvent;
// create event for use by plugins
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
carbonEvent.what = mouseDown;
carbonEvent.message = 0;
carbonEvent.when = ::TickCount();
::GetGlobalMouse(&carbonEvent.where);
carbonEvent.modifiers = controlKey; // fake a context menu click
geckoEvent.nativeMsg = &carbonEvent;
}
else {
InitNPCocoaEvent(&cocoaEvent);
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
cocoaEvent.type = NPCocoaEventMouseDown;
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
cocoaEvent.data.mouse.pluginX = point.x;
cocoaEvent.data.mouse.pluginY = point.y;
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
geckoEvent.nativeMsg = &cocoaEvent;
}
PRBool handled = mGeckoChild->DispatchWindowEvent(geckoEvent);
if (!mGeckoChild)
@ -3370,14 +3542,31 @@ static nsEventStatus SendGeckoMouseEnterOrExitEvent(PRBool isTrusted,
geckoEvent.button = nsMouseEvent::eRightButton;
geckoEvent.clickCount = [theEvent clickCount];
// create native EventRecord for use by plugins
EventRecord macEvent;
macEvent.what = mouseUp;
macEvent.message = 0;
macEvent.when = ::TickCount();
::GetGlobalMouse(&macEvent.where);
macEvent.modifiers = controlKey; // fake a context menu click
geckoEvent.nativeMsg = &macEvent;
// create event for use by plugins
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
carbonEvent.what = mouseUp;
carbonEvent.message = 0;
carbonEvent.when = ::TickCount();
::GetGlobalMouse(&carbonEvent.where);
carbonEvent.modifiers = controlKey; // fake a context menu click
geckoEvent.nativeMsg = &carbonEvent;
}
else {
InitNPCocoaEvent(&cocoaEvent);
NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
cocoaEvent.type = NPCocoaEventMouseUp;
cocoaEvent.data.mouse.modifierFlags = [theEvent modifierFlags];
cocoaEvent.data.mouse.pluginX = point.x;
cocoaEvent.data.mouse.pluginY = point.y;
cocoaEvent.data.mouse.buttonNumber = [theEvent buttonNumber];
cocoaEvent.data.mouse.clickCount = [theEvent clickCount];
cocoaEvent.data.mouse.deltaX = [theEvent deltaX];
cocoaEvent.data.mouse.deltaY = [theEvent deltaY];
cocoaEvent.data.mouse.deltaZ = [theEvent deltaZ];
geckoEvent.nativeMsg = &cocoaEvent;
}
nsAutoRetainCocoaObject kungFuDeathGrip(self);
mGeckoChild->DispatchWindowEvent(geckoEvent);
@ -3684,6 +3873,32 @@ static PRBool ConvertUnicodeToCharCode(PRUnichar inUniChar, unsigned char* outCh
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(PR_FALSE);
}
static void ConvertCocoaKeyEventToNPCocoaEvent(NSEvent* cocoaEvent, NPCocoaEvent& pluginEvent, PRUint32 keyType = 0)
{
NSEventType nativeType = [cocoaEvent type];
switch (nativeType) {
case NSKeyDown:
pluginEvent.type = NPCocoaEventKeyDown;
break;
case NSKeyUp:
pluginEvent.type = NPCocoaEventKeyUp;
break;
case NSFlagsChanged:
pluginEvent.type = NPCocoaEventFlagsChanged;
break;
default:
printf("Asked to convert key event of unknown type to Cocoa plugin event!");
}
pluginEvent.data.key.modifierFlags = [cocoaEvent modifierFlags];
// don't try to access character data for flags changed events, it will raise an exception
if (nativeType != NSFlagsChanged) {
pluginEvent.data.key.characters = (NPNSString*)[cocoaEvent characters];
pluginEvent.data.key.charactersIgnoringModifiers = (NPNSString*)[cocoaEvent charactersIgnoringModifiers];
pluginEvent.data.key.isARepeat = [cocoaEvent isARepeat];
pluginEvent.data.key.keyCode = [cocoaEvent keyCode];
}
}
static void ConvertCocoaKeyEventToCarbonEvent(NSEvent* cocoaEvent, EventRecord& pluginEvent, PRUint32 keyType = 0)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
@ -4651,15 +4866,20 @@ GetUSLayoutCharFromKeyTranslate(UInt32 aKeyCode, UInt32 aModifiers)
// -insertText: they've already been taken into account in creating
// the input string.
// create native EventRecord for use by plugins
EventRecord macEvent;
// create event for use by plugins
EventRecord carbonEvent;
if (mCurKeyEvent) {
// XXX The ASCII characters inputting mode of egbridge (Japanese IME)
// might send the keyDown event with wrong keyboard layout if other
// keyboard layouts are already loaded. In that case, the native event
// doesn't match to this gecko event...
ConvertCocoaKeyEventToCarbonEvent(mCurKeyEvent, macEvent);
geckoEvent.nativeMsg = &macEvent;
if (mSendCarbonPluginEvents) {
ConvertCocoaKeyEventToCarbonEvent(mCurKeyEvent, carbonEvent);
geckoEvent.nativeMsg = &carbonEvent;
}
else {
geckoEvent.nativeMsg = NULL;
}
geckoEvent.isShift = (nsCocoaUtils::GetCocoaEventModifierFlags(mCurKeyEvent) & NSShiftKeyMask) != 0;
if (!IsPrintableChar(geckoEvent.charCode)) {
geckoEvent.keyCode =
@ -5059,10 +5279,17 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_DOWN, nsnull);
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
// create native EventRecord for use by plugins
EventRecord macEvent;
ConvertCocoaKeyEventToCarbonEvent(theEvent, macEvent);
geckoEvent.nativeMsg = &macEvent;
// create event for use by plugins
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
ConvertCocoaKeyEventToCarbonEvent(theEvent, carbonEvent);
geckoEvent.nativeMsg = &carbonEvent;
}
else {
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent);
geckoEvent.nativeMsg = &cocoaEvent;
}
mKeyDownHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
if (!mGeckoChild)
@ -5105,10 +5332,15 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
if (mKeyDownHandled)
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
// create native EventRecord for use by plugins
EventRecord macEvent;
ConvertCocoaKeyEventToCarbonEvent(theEvent, macEvent);
geckoEvent.nativeMsg = &macEvent;
// create event for use by plugins
EventRecord carbonEvent;
if (mSendCarbonPluginEvents) {
ConvertCocoaKeyEventToCarbonEvent(theEvent, carbonEvent);
geckoEvent.nativeMsg = &carbonEvent;
}
else {
geckoEvent.nativeMsg = NULL;
}
mKeyPressHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
mKeyPressSent = YES;
@ -5142,10 +5374,15 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
if (mKeyDownHandled)
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
// create native EventRecord for use by plugins
EventRecord macEvent;
ConvertCocoaKeyEventToCarbonEvent(theEvent, macEvent);
geckoEvent.nativeMsg = &macEvent;
// create event for use by plugins
EventRecord carbonEvent;
if (mSendCarbonPluginEvents) {
ConvertCocoaKeyEventToCarbonEvent(theEvent, carbonEvent);
geckoEvent.nativeMsg = &carbonEvent;
}
else {
geckoEvent.nativeMsg = NULL;
}
mKeyPressHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
}
@ -5228,7 +5465,7 @@ static const char* ToEscapedString(NSString* aString, nsCAutoString& aBuf)
// work in plugins like the Flash plugin). The same strategy is used by the
// WebKit. See PluginKeyEventsHandler() and [ChildView processPluginKeyEvent:]
// for more info.
if (mGeckoChild && mIsPluginView) {
if (mGeckoChild && mIsPluginView && mSendCarbonPluginEvents) {
[self activatePluginTSMDoc];
// We use the active TSM document to pass a pointer to ourselves (the
// currently focused ChildView) to PluginKeyEventsHandler(). Because this
@ -5270,6 +5507,16 @@ static BOOL keyUpAlreadySentKeyDown = NO;
nsAutoRetainCocoaObject kungFuDeathGrip(self);
if (mIsPluginView) {
if (!mSendCarbonPluginEvents) {
nsKeyEvent keyUpEvent(PR_TRUE, NS_KEY_UP, nsnull);
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&keyUpEvent];
NPCocoaEvent pluginEvent;
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, pluginEvent);
keyUpEvent.nativeMsg = &pluginEvent;
mGeckoChild->DispatchWindowEvent(keyUpEvent);
return;
}
// I'm not sure the call to TSMProcessRawKeyEvent() is needed here (though
// WebKit makes one).
::TSMProcessRawKeyEvent([theEvent _eventRef]);
@ -5319,10 +5566,8 @@ static BOOL keyUpAlreadySentKeyDown = NO;
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_DOWN, nsnull);
[self convertCocoaKeyEvent:nativeKeyDownEvent toGeckoEvent:&geckoEvent];
// create native EventRecord for use by plugins
EventRecord macEvent;
ConvertCocoaKeyEventToCarbonEvent(nativeKeyDownEvent, macEvent);
geckoEvent.nativeMsg = &macEvent;
// plugin case returned out early, we don't need a native event here
geckoEvent.nativeMsg = NULL;
keyDownHandled = mGeckoChild->DispatchWindowEvent(geckoEvent);
if (!mGeckoChild)
@ -5347,10 +5592,8 @@ static BOOL keyUpAlreadySentKeyDown = NO;
if (keyDownHandled)
geckoEvent.flags |= NS_EVENT_FLAG_NO_DEFAULT;
// create native EventRecord for use by plugins
EventRecord macEvent;
ConvertCocoaKeyEventToCarbonEvent(nativeKeyDownEvent, macEvent);
geckoEvent.nativeMsg = &macEvent;
// plugin case returned out early, we don't need a native event here
geckoEvent.nativeMsg = NULL;
mGeckoChild->DispatchWindowEvent(geckoEvent);
if (!mGeckoChild)
@ -5360,10 +5603,8 @@ static BOOL keyUpAlreadySentKeyDown = NO;
nsKeyEvent geckoEvent(PR_TRUE, NS_KEY_UP, nsnull);
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
// create native EventRecord for use by plugins
EventRecord macEvent;
ConvertCocoaKeyEventToCarbonEvent(theEvent, macEvent);
geckoEvent.nativeMsg = &macEvent;
// plugin case returned out early, we don't need a native event here
geckoEvent.nativeMsg = NULL;
mGeckoChild->DispatchWindowEvent(geckoEvent);
@ -5539,10 +5780,17 @@ static BOOL keyUpAlreadySentKeyDown = NO;
nsKeyEvent geckoEvent(PR_TRUE, message, nsnull);
[self convertCocoaKeyEvent:theEvent toGeckoEvent:&geckoEvent];
// create native EventRecord for use by plugins
EventRecord macEvent;
ConvertCocoaKeyEventToCarbonEvent(theEvent, macEvent, message);
geckoEvent.nativeMsg = &macEvent;
// create event for use by plugins
EventRecord carbonEvent;
NPCocoaEvent cocoaEvent;
if (mSendCarbonPluginEvents) {
ConvertCocoaKeyEventToCarbonEvent(theEvent, carbonEvent, message);
geckoEvent.nativeMsg = &carbonEvent;
}
else {
ConvertCocoaKeyEventToNPCocoaEvent(theEvent, cocoaEvent, message);
geckoEvent.nativeMsg = &cocoaEvent;
}
mGeckoChild->DispatchWindowEvent(geckoEvent);