Bug 1092630: Get rid of native widgets for OS X NPAPI plugins, make things work much better under e10s. Patch by Josh Aas, Markus Stange, Steven Michaud, David Parks. r=smichaud/jst/josh (more reviews pending)

This commit is contained in:
Josh Aas 2014-12-11 08:44:07 -06:00
parent 4aad711842
commit 6141b5290e
48 changed files with 1122 additions and 2504 deletions

View File

@ -910,7 +910,8 @@ nsFrameLoader::ShowRemoteFrame(const nsIntSize& size,
// Don't show remote iframe if we are waiting for the completion of reflow.
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
mRemoteBrowser->UpdateDimensions(dimensions, size);
nsIntPoint chromeDisp = aFrame->GetChromeDisplacement();
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
}
}
@ -1942,7 +1943,8 @@ nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
nsIntSize size = aIFrame->GetSubdocumentSize();
nsIntRect dimensions;
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
mRemoteBrowser->UpdateDimensions(dimensions, size);
nsIntPoint chromeDisp = aIFrame->GetChromeDisplacement();
mRemoteBrowser->UpdateDimensions(dimensions, size, chromeDisp);
}
return NS_OK;
}

View File

@ -440,7 +440,8 @@ child:
CacheFileDescriptor(nsString path, FileDescriptor fd);
UpdateDimensions(nsIntRect rect, nsIntSize size, ScreenOrientation orientation) compress;
UpdateDimensions(nsIntRect rect, nsIntSize size, ScreenOrientation orientation,
nsIntPoint chromeDisp) compress;
UpdateFrame(FrameMetrics frame);

View File

@ -2010,13 +2010,15 @@ TabChild::RecvShow(const nsIntSize& aSize,
}
bool
TabChild::RecvUpdateDimensions(const nsIntRect& rect, const nsIntSize& size, const ScreenOrientation& orientation)
TabChild::RecvUpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
const ScreenOrientation& orientation, const nsIntPoint& chromeDisp)
{
if (!mRemoteFrame) {
return true;
}
mOuterRect = rect;
mChromeDisp = chromeDisp;
bool initialSizing = !HasValidInnerSize()
&& (size.width != 0 && size.height != 0);

View File

@ -324,7 +324,8 @@ public:
PRenderFrameChild* aRenderFrame) MOZ_OVERRIDE;
virtual bool RecvUpdateDimensions(const nsIntRect& rect,
const nsIntSize& size,
const ScreenOrientation& orientation) MOZ_OVERRIDE;
const ScreenOrientation& orientation,
const nsIntPoint& chromeDisp) MOZ_OVERRIDE;
virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
const uint32_t& aScrollGeneration) MOZ_OVERRIDE;
@ -495,6 +496,8 @@ public:
bool DeallocPPluginWidgetChild(PPluginWidgetChild* aActor) MOZ_OVERRIDE;
already_AddRefed<nsIWidget> CreatePluginWidget(nsIWidget* aParent);
nsIntPoint GetChromeDisplacement() { return mChromeDisp; };
protected:
virtual ~TabChild();
@ -653,6 +656,8 @@ private:
nsRefPtr<ActiveElementManager> mActiveElementManager;
bool mHasValidInnerSize;
bool mDestroyed;
// Position of tab, relative to parent widget (typically the window)
nsIntPoint mChromeDisp;
TabId mUniqueId;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);

View File

@ -618,7 +618,8 @@ TabParent::Show(const nsIntSize& size)
}
void
TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size)
TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
const nsIntPoint& aChromeDisp)
{
if (mIsDestroyed) {
return;
@ -634,7 +635,7 @@ TabParent::UpdateDimensions(const nsIntRect& rect, const nsIntSize& size)
mDimensions = size;
mOrientation = orientation;
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation);
unused << SendUpdateDimensions(mRect, mDimensions, mOrientation, aChromeDisp);
}
}

View File

@ -225,7 +225,8 @@ public:
// message-sending functions under a layer of indirection and
// eating the return values
void Show(const nsIntSize& size);
void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size);
void UpdateDimensions(const nsIntRect& rect, const nsIntSize& size,
const nsIntPoint& chromeDisp);
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
void UIResolutionChanged();
void AcknowledgeScrollUpdate(const ViewID& aScrollId, const uint32_t& aScrollGeneration);

View File

@ -98,10 +98,12 @@ MSVC_ENABLE_PGO = True
LOCAL_INCLUDES += [
'/dom/base',
'/dom/plugins/ipc',
'/layout/generic',
'/layout/xul',
'/widget',
'/widget/android',
'/widget/cocoa',
'/xpcom/base',
]

View File

@ -52,6 +52,7 @@
#include <ApplicationServices/ApplicationServices.h>
#include <OpenGL/OpenGL.h>
#include "nsCocoaFeatures.h"
#include "PluginUtilsOSX.h"
#endif
// needed for nppdf plugin
@ -2121,13 +2122,13 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
}
case NPNVsupportsCoreAnimationBool: {
*(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
*(NPBool*)result = true;
return NPERR_NO_ERROR;
}
case NPNVsupportsInvalidatingCoreAnimationBool: {
*(NPBool*)result = nsCocoaFeatures::SupportCoreAnimationPlugins();
*(NPBool*)result = true;
return NPERR_NO_ERROR;
}
@ -2784,11 +2785,50 @@ _unscheduletimer(NPP instance, uint32_t timerID)
NPError
_popupcontextmenu(NPP instance, NPMenu* menu)
{
#ifdef MOZ_WIDGET_COCOA
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
if (!inst)
double pluginX, pluginY;
double screenX, screenY;
const NPCocoaEvent* currentEvent = static_cast<NPCocoaEvent*>(inst->GetCurrentEvent());
if (!currentEvent) {
return NPERR_GENERIC_ERROR;
}
// Ensure that the events has an x/y value.
if (currentEvent->type != NPCocoaEventMouseDown &&
currentEvent->type != NPCocoaEventMouseUp &&
currentEvent->type != NPCocoaEventMouseMoved &&
currentEvent->type != NPCocoaEventMouseEntered &&
currentEvent->type != NPCocoaEventMouseExited &&
currentEvent->type != NPCocoaEventMouseDragged) {
return NPERR_GENERIC_ERROR;
}
pluginX = currentEvent->data.mouse.pluginX;
pluginY = currentEvent->data.mouse.pluginY;
if ((pluginX < 0.0) || (pluginY < 0.0))
return NPERR_GENERIC_ERROR;
return inst->PopUpContextMenu(menu);
NPBool success = _convertpoint(instance,
pluginX, pluginY, NPCoordinateSpacePlugin,
&screenX, &screenY, NPCoordinateSpaceScreen);
if (success) {
return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
screenX, screenY,
nullptr,
nullptr);
} else {
NS_WARNING("Convertpoint failed, could not created contextmenu.");
return NPERR_GENERIC_ERROR;
}
#else
NS_WARNING("Not supported on this platform!");
return NPERR_GENERIC_ERROR;
#endif
}
NPBool

View File

@ -173,25 +173,26 @@ static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance)
nsNPAPIPluginInstance::nsNPAPIPluginInstance()
:
mDrawingModel(kDefaultDrawingModel),
: mDrawingModel(kDefaultDrawingModel)
#ifdef MOZ_WIDGET_ANDROID
mANPDrawingModel(0),
mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary),
mWakeLocked(false),
mFullScreen(false),
mInverted(false),
, mANPDrawingModel(0)
, mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary)
, mWakeLocked(false)
, mFullScreen(false)
, mInverted(false)
#endif
, mRunning(NOT_STARTED)
, mWindowless(false)
, mTransparent(false)
, mCached(false)
, mUsesDOMForCursor(false)
, mInPluginInitCall(false)
, mPlugin(nullptr)
, mMIMEType(nullptr)
, mOwner(nullptr)
#ifdef XP_MACOSX
, mCurrentPluginEvent(nullptr)
#endif
mRunning(NOT_STARTED),
mWindowless(false),
mTransparent(false),
mCached(false),
mUsesDOMForCursor(false),
mInPluginInitCall(false),
mPlugin(nullptr),
mMIMEType(nullptr),
mOwner(nullptr),
mCurrentPluginEvent(nullptr)
#ifdef MOZ_WIDGET_ANDROID
, mOnScreen(true)
#endif
@ -671,7 +672,9 @@ nsresult nsNPAPIPluginInstance::HandleEvent(void* event, int16_t* result,
int16_t tmpResult = kNPEventNotHandled;
if (pluginFunctions->event) {
#ifdef XP_MACOSX
mCurrentPluginEvent = event;
#endif
#if defined(XP_WIN)
NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event), this,
aSafeToReenterGecko);
@ -685,7 +688,9 @@ nsresult nsNPAPIPluginInstance::HandleEvent(void* event, int16_t* result,
if (result)
*result = tmpResult;
#ifdef XP_MACOSX
mCurrentPluginEvent = nullptr;
#endif
}
return NS_OK;
@ -1152,7 +1157,8 @@ nsNPAPIPluginInstance::ShouldCache()
nsresult
nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
{
#ifdef MOZ_WIDGET_ANDROID
#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)
// All OS X plugins are windowless.
// On android, pre-honeycomb, all plugins are treated as windowless.
*isWindowless = true;
#else
@ -1511,23 +1517,13 @@ 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)
if (mOwner) {
return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY, destSpace);
}
return false;
}

View File

@ -134,6 +134,10 @@ public:
void RedrawPlugin();
#ifdef XP_MACOSX
void SetEventModel(NPEventModel aModel);
void* GetCurrentEvent() {
return mCurrentPluginEvent;
}
#endif
#ifdef MOZ_WIDGET_ANDROID
@ -261,7 +265,6 @@ public:
nsNPAPITimer* TimerWithID(uint32_t id, uint32_t* 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);
@ -368,8 +371,10 @@ private:
nsTArray<nsNPAPITimer*> mTimers;
#ifdef XP_MACOSX
// non-null during a HandleEvent call
void* mCurrentPluginEvent;
#endif
// Timestamp for the last time this plugin was stopped.
// This is only valid when the plugin is actually stopped!

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,12 @@ namespace mozilla {
namespace dom {
struct MozPluginParameter;
}
namespace widget {
class PuppetWidget;
}
}
using mozilla::widget::PuppetWidget;
#ifdef MOZ_X11
class gfxXlibSurface;
@ -62,6 +67,7 @@ public:
NS_IMETHOD ShowStatus(const char16_t *aStatusMsg) MOZ_OVERRIDE;
// This can go away, just leaving it here to avoid changing the interface.
NPError ShowNativeContextMenu(NPMenu* menu, void* event) MOZ_OVERRIDE;
NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
@ -108,7 +114,7 @@ public:
nsresult Init(nsIContent* aContent);
void* GetPluginPortFromWidget();
void* GetPluginPort();
void ReleasePluginPort(void* pluginPort);
nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent);
@ -116,6 +122,11 @@ public:
#ifdef XP_MACOSX
enum { ePluginPaintEnable, ePluginPaintDisable };
void WindowFocusMayHaveChanged();
void ResolutionMayHaveChanged();
bool WindowIsActive();
void SendWindowFocusChanged(bool aIsActive);
NPDrawingModel GetDrawingModel();
bool IsRemoteDrawingCoreAnimation();
nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
@ -124,19 +135,14 @@ public:
void AddToCARefreshTimer();
void RemoveFromCARefreshTimer();
// This calls into the plugin (NPP_SetWindow) and can run script.
void* FixUpPluginWindow(int32_t inPaintState);
void FixUpPluginWindow(int32_t inPaintState);
void HidePluginWindow();
// Set a flag that (if true) indicates the plugin port info has changed and
// SetWindow() needs to be called.
void SetPluginPortChanged(bool 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.
void* GetPluginPortCopy();
// Set plugin port info in the plugin (in the 'window' member of the
// NPWindow 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.
void* SetPluginPortAndDetectChange();
// NPWindow structure passed to the plugin by SetWindow()).
void SetPluginPort();
// Flag when we've set up a Thebes (and CoreGraphics) context in
// nsPluginFrame::PaintPlugin(). We need to know this in
// FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
@ -288,6 +294,11 @@ private:
static nsCOMPtr<nsITimer> *sCATimer;
static nsTArray<nsPluginInstanceOwner*> *sCARefreshListeners;
bool mSentInitialTopLevelWindowEvent;
bool mLastWindowIsActive;
bool mLastContentFocused;
double mLastScaleFactor;
// True if, the next time the window is activated, we should blur ourselves.
bool mShouldBlurOnActivate;
#endif
// Initially, the event loop nesting level we were created on, it's updated
@ -296,9 +307,6 @@ private:
uint32_t mLastEventloopNestingLevel;
bool mContentFocused;
bool mWidgetVisible; // used on Mac to store our widget's visible state
#ifdef XP_MACOSX
bool mPluginPortChanged;
#endif
#ifdef MOZ_X11
// Used with windowless plugins only, initialized in CreateWidget().
bool mFlash10Quirks;
@ -323,6 +331,16 @@ private:
bool aAllowPropagate = false);
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
#ifdef XP_MACOSX
static NPBool ConvertPointPuppet(PuppetWidget *widget, nsPluginFrame* pluginFrame,
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace);
static NPBool ConvertPointNoPuppet(nsIWidget *widget, nsPluginFrame* pluginFrame,
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace);
void PerformDelayedBlurs();
#endif // XP_MACOSX
int mLastMouseDownButtonType;
#ifdef MOZ_X11

View File

@ -388,12 +388,12 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
}
case NPNVsupportsCoreAnimationBool: {
*((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
*((NPBool*)aValue) = true;
return NPERR_NO_ERROR;
}
case NPNVsupportsInvalidatingCoreAnimationBool: {
*((NPBool*)aValue) = nsCocoaFeatures::SupportCoreAnimationPlugins();
*((NPBool*)aValue) = true;
return NPERR_NO_ERROR;
}

View File

@ -220,26 +220,32 @@ NPError mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(void* aMenu, int
// change to an arrow cursor automatically -- as it does in Chrome.
[[NSCursor arrowCursor] set];
EventProcessor* eventProcessor = nullptr;
NSTimer *eventTimer = nullptr;
if (pluginModule) {
// Create a timer to process browser events while waiting
// on the menu. This prevents the browser from hanging
// during the lifetime of the menu.
EventProcessor* eventProcessor = [[EventProcessor alloc] init];
eventProcessor = [[EventProcessor alloc] init];
[eventProcessor setRemoteEvents:remoteEvent pluginModule:pluginModule];
NSTimer *eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
eventTimer = [NSTimer timerWithTimeInterval:EVENT_PROCESS_DELAY
target:eventProcessor selector:@selector(onTick)
userInfo:nil repeats:TRUE];
// Use NSEventTrackingRunLoopMode otherwise the timer will
// not fire during the right click menu.
[[NSRunLoop currentRunLoop] addTimer:eventTimer
forMode:NSEventTrackingRunLoopMode];
}
NSMenu* nsmenu = reinterpret_cast<NSMenu*>(aMenu);
NSPoint screen_point = ::NSMakePoint(aX, aY);
[nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil];
if (pluginModule) {
[eventTimer invalidate];
[eventProcessor release];
}
return NPERR_NO_ERROR;

View File

@ -59,7 +59,7 @@
utils.sendNativeMouseEvent(plugin1X, plugin1Y, NSLeftMouseUp, 0, plugin1);
expectedEventCount++;
is(plugin1.getFocusState(), true, "Plugin should have focus.");
is(plugin1.getFocusState(), true, "(1) Plugin should have focus.");
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
// Make sure window activation state changes don't spontaneously
@ -68,13 +68,13 @@
// Blur the window.
window.blur();
is(plugin1.getFocusState(), true, "Plugin should still have focus.");
is(plugin1.getFocusState(), true, "(2) Plugin should still have focus.");
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
// Focus the window.
window.focus();
is(plugin1.getFocusState(), true, "Plugin should still have focus.");
is(plugin1.getFocusState(), true, "(3) Plugin should still have focus.");
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
// Take focus from the plugin.
@ -82,7 +82,7 @@
utils.sendNativeMouseEvent(plugin2X, plugin2Y, NSLeftMouseUp, 0, plugin2);
expectedEventCount++;
is(plugin1.getFocusState(), false, "Plugin should not have focus.");
is(plugin1.getFocusState(), false, "(4) Plugin should not have focus.");
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
// Make sure window activation causes the plugin to be informed of focus
@ -99,14 +99,14 @@
// Take focus from the plugin while the window is blurred.
plugin2.focus();
is(plugin1.getFocusState(), true, "Plugin should still have focus.");
is(plugin1.getFocusState(), true, "(5) Plugin should still have focus.");
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
// Focus the window.
window.focus();
expectedEventCount++;
is(plugin1.getFocusState(), false, "Plugin should not have focus.");
is(plugin1.getFocusState(), false, "(6) Plugin should not have focus.");
is(plugin1.getFocusEventCount(), expectedEventCount, "Focus event count should be " + expectedEventCount);
window.opener.testsFinished();

View File

@ -29,11 +29,10 @@ function runTests() {
var domWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var devPxPerCSSPx = domWindowUtils.screenPixelsPerCSSPixel;
var pluginRect = pluginElement.getBoundingClientRect();
var pluginX = (pluginRect.left * devPxPerCSSPx) + ((window.mozInnerScreenX * devPxPerCSSPx) - window.screenX);
var pluginY = (pluginRect.top * devPxPerCSSPx) + ((window.mozInnerScreenY * devPxPerCSSPx) - window.screenY);
var pluginX = pluginRect.left + (window.mozInnerScreenX - window.screenX);
var pluginY = pluginRect.top + (window.mozInnerScreenY - window.screenY);
var windowX = window.screenX;
var windowY = window.screenY;

View File

@ -3394,7 +3394,7 @@ getTopLevelWindowActivationEventCount(NPObject* npobj, const NPVariant* args, ui
}
// Returns top-level window activation state as indicated by Cocoa NPAPI's
// NPCocoaEventWindowFocusChanged events - 'true' if active, 'false' if not.
// NPCocoaEventFocusChanged events - 'true' if active, 'false' if not.
// Throws an exception if no events have been received and thus this state
// is unknown.
bool

View File

@ -238,6 +238,7 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
case NPCocoaEventMouseDown:
case NPCocoaEventMouseUp:
case NPCocoaEventMouseMoved:
case NPCocoaEventMouseDragged:
instanceData->lastMouseX = (int32_t)cocoaEvent->data.mouse.pluginX;
instanceData->lastMouseY = (int32_t)cocoaEvent->data.mouse.pluginY;
if (cocoaEvent->type == NPCocoaEventMouseUp) {

View File

@ -2931,6 +2931,8 @@ nsRootPresContext::CancelApplyPluginGeometryTimer()
}
}
#ifndef XP_MACOSX
static bool
HasOverlap(const nsIntPoint& aOffset1, const nsTArray<nsIntRect>& aClipRects1,
const nsIntPoint& aOffset2, const nsTArray<nsIntRect>& aClipRects2)
@ -2999,18 +3001,6 @@ SortConfigurations(nsTArray<nsIWidget::Configuration>* aConfigurations)
}
}
static PLDHashOperator
PluginDidSetGeometryEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
{
nsPluginFrame* f = static_cast<nsPluginFrame*>(aEntry->GetKey()->GetPrimaryFrame());
if (!f) {
NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
return PL_DHASH_NEXT;
}
f->DidSetWidgetGeometry();
return PL_DHASH_NEXT;
}
struct PluginGetGeometryUpdateClosure {
nsTArray<nsIWidget::Configuration> mConfigurations;
};
@ -3028,9 +3018,24 @@ PluginGetGeometryUpdate(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
return PL_DHASH_NEXT;
}
#endif // #ifndef XP_MACOSX
static PLDHashOperator
PluginDidSetGeometryEnumerator(nsRefPtrHashKey<nsIContent>* aEntry, void* userArg)
{
nsPluginFrame* f = static_cast<nsPluginFrame*>(aEntry->GetKey()->GetPrimaryFrame());
if (!f) {
NS_WARNING("Null frame in PluginDidSetGeometryEnumerator");
return PL_DHASH_NEXT;
}
f->DidSetWidgetGeometry();
return PL_DHASH_NEXT;
}
void
nsRootPresContext::ApplyPluginGeometryUpdates()
{
#ifndef XP_MACOSX
CancelApplyPluginGeometryTimer();
PluginGetGeometryUpdateClosure closure;
@ -3042,6 +3047,8 @@ nsRootPresContext::ApplyPluginGeometryUpdates()
SortConfigurations(&closure.mConfigurations);
widget->ConfigureChildren(closure.mConfigurations);
}
#endif // #ifndef XP_MACOSX
mRegisteredPlugins.EnumerateEntries(PluginDidSetGeometryEnumerator, nullptr);
}

View File

@ -106,11 +106,6 @@ SOURCES += [
'nsPluginFrame.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
UNIFIED_SOURCES += [
'nsPluginUtilsOSX.mm',
]
FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
MSVC_ENABLE_PGO = True

View File

@ -69,7 +69,6 @@
#ifdef XP_MACOSX
#include "gfxQuartzNativeDrawing.h"
#include "nsPluginUtilsOSX.h"
#include "mozilla/gfx/QuartzSupport.h"
#endif
@ -103,43 +102,6 @@ GetObjectFrameLog()
}
#endif /* PR_LOGGING */
#if defined(XP_MACOSX) && !defined(__LP64__)
// The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
// and up (though the QuickDraw APIs defined in them are still present) -- so
// we need to supply the relevant parts of their contents here. It's likely
// that Apple will eventually remove the APIs themselves (probably in OS X
// 10.8), so we need to make them weak imports, and test for their presence
// before using them.
extern "C" {
#if !defined(__QUICKDRAWAPI__)
extern void SetRect(
Rect * r,
short left,
short top,
short right,
short bottom)
__attribute__((weak_import));
#endif /* __QUICKDRAWAPI__ */
#if !defined(__QDOFFSCREEN__)
extern QDErr NewGWorldFromPtr(
GWorldPtr * offscreenGWorld,
UInt32 PixelFormat,
const Rect * boundsRect,
CTabHandle cTable, /* can be nullptr */
GDHandle aGDevice, /* can be nullptr */
GWorldFlags flags,
Ptr newBuffer,
SInt32 rowBytes)
__attribute__((weak_import));
extern void DisposeGWorld(GWorldPtr offscreenGWorld)
__attribute__((weak_import));
#endif /* __QDOFFSCREEN__ */
}
#endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::layers;
@ -220,7 +182,7 @@ nsPluginFrame::AccessibleType()
#ifdef XP_WIN
NS_IMETHODIMP nsPluginFrame::GetPluginPort(HWND *aPort)
{
*aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
*aPort = (HWND) mInstanceOwner->GetPluginPort();
return NS_OK;
}
#endif
@ -388,10 +350,7 @@ nsPluginFrame::PrepForDrawing(nsIWidget *aWidget)
} else {
// Changing to windowless mode changes the NPWindow geometry.
FixupWindow(GetContentRectRelativeToSelf().Size());
#ifndef XP_MACOSX
RegisterPluginForGeometryUpdates();
#endif
}
if (!IsHidden()) {
@ -577,14 +536,6 @@ nsPluginFrame::FixupWindow(const nsSize& aSize)
NS_ENSURE_TRUE_VOID(window);
#ifdef XP_MACOSX
nsWeakFrame weakFrame(this);
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
if (!weakFrame.IsAlive()) {
return;
}
#endif
bool windowless = (window->type == NPWindowTypeDrawable);
nsIntPoint origin = GetWindowOriginInPixels(windowless);
@ -600,15 +551,7 @@ nsPluginFrame::FixupWindow(const nsSize& aSize)
window->width = presContext->AppUnitsToDevPixels(aSize.width) / intScaleFactor;
window->height = presContext->AppUnitsToDevPixels(aSize.height) / intScaleFactor;
// 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.
#ifdef XP_MACOSX
window->clipRect.top = 0;
window->clipRect.left = 0;
window->clipRect.bottom = 0;
window->clipRect.right = 0;
#else
#ifndef XP_MACOSX
mInstanceOwner->UpdateWindowPositionAndClipRect(false);
#endif
@ -630,19 +573,15 @@ nsPluginFrame::CallSetWindow(bool aCheckIsHidden)
return rv;
nsPluginNativeWindow *window = (nsPluginNativeWindow *)win;
#ifdef XP_MACOSX
nsWeakFrame weakFrame(this);
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintDisable);
if (!weakFrame.IsAlive()) {
return NS_ERROR_NOT_AVAILABLE;
}
#endif
if (aCheckIsHidden && IsHidden())
return NS_ERROR_FAILURE;
// refresh the plugin port as well
window->window = mInstanceOwner->GetPluginPortFromWidget();
#ifdef XP_MACOSX
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
#endif
window->window = mInstanceOwner->GetPluginPort();
// Adjust plugin dimensions according to pixel snap results
// and reduce amount of SetWindow calls
@ -1064,11 +1003,7 @@ nsPluginFrame::NotifyPluginReflowObservers()
void
nsPluginFrame::DidSetWidgetGeometry()
{
#if defined(XP_MACOSX)
if (mInstanceOwner) {
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
}
#else
#ifndef XP_MACOSX
if (!mWidget && mInstanceOwner) {
// UpdateWindowVisibility will notify the plugin of position changes
// by updating the NPWindow and calling NPP_SetWindow/AsyncSetWindow.
@ -1079,6 +1014,8 @@ nsPluginFrame::DidSetWidgetGeometry()
nsLayoutUtils::IsPopup(nsLayoutUtils::GetDisplayRootFrame(this)) ||
!mNextConfigurationBounds.IsEmpty());
}
#else
CallSetWindow(false);
#endif
}
@ -1086,7 +1023,6 @@ bool
nsPluginFrame::IsOpaque() const
{
#if defined(XP_MACOSX)
// ???
return false;
#elif defined(MOZ_WIDGET_ANDROID)
// We don't know, so just assume transparent
@ -1100,7 +1036,6 @@ bool
nsPluginFrame::IsTransparentMode() const
{
#if defined(XP_MACOSX)
// ???
return false;
#else
if (!mInstanceOwner)
@ -1153,7 +1088,12 @@ nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
}
#endif
if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
if (aBuilder->IsForPainting() && mInstanceOwner) {
#ifdef XP_MACOSX
mInstanceOwner->ResolutionMayHaveChanged();
mInstanceOwner->WindowFocusMayHaveChanged();
#endif
if (mInstanceOwner->UseAsyncRendering()) {
NPWindow* window = nullptr;
mInstanceOwner->GetWindow(window);
bool isVisible = window && window->width > 0 && window->height > 0;
@ -1165,6 +1105,7 @@ nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
mInstanceOwner->NotifyPaintWaiter(aBuilder);
}
}
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
clip(aBuilder, this);
@ -1253,117 +1194,10 @@ nsPluginFrame::PrintPlugin(nsRenderingContext& aRenderingContext,
window.clipRect.left = 0; window.clipRect.right = 0;
// platform specific printing code
#if defined(XP_MACOSX) && !defined(__LP64__)
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
// Don't use this code if any of the QuickDraw APIs it currently requires
// are missing (as they probably will be on OS X 10.8 and up).
if (!&::SetRect || !&::NewGWorldFromPtr || !&::DisposeGWorld) {
NS_WARNING("Cannot print plugin -- required QuickDraw APIs are missing!");
return;
}
nsSize contentSize = GetContentRectRelativeToSelf().Size();
window.x = 0;
window.y = 0;
window.width = presContext->AppUnitsToDevPixels(contentSize.width);
window.height = presContext->AppUnitsToDevPixels(contentSize.height);
gfxContext *ctx = aRenderingContext.ThebesContext();
if (!ctx)
return;
gfxContextAutoSaveRestore save(ctx);
ctx->NewPath();
gfx::Rect rect(window.x, window.y, window.width, window.height);
ctx->Rectangle(ThebesRect(rect));
ctx->Clip();
gfxQuartzNativeDrawing nativeDraw(aDrawTarget, rect);
CGContextRef cgContext = nativeDraw.BeginNativeDrawing();
if (!cgContext) {
nativeDraw.EndNativeDrawing();
return;
}
window.clipRect.right = window.width;
window.clipRect.bottom = window.height;
window.type = NPWindowTypeDrawable;
::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,
nullptr, nullptr, 0,
buffer.Elements(), window.width * 4) != noErr) {
::CGContextRelease(cgBuffer);
nativeDraw.EndNativeDrawing();
return;
}
window.clipRect.right = window.width;
window.clipRect.bottom = window.height;
window.type = NPWindowTypeDrawable;
// 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 = &gWorld;
npprint.print.embedPrint.platformPrint = gWorld;
npprint.print.embedPrint.window = window;
pi->Print(&npprint);
::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);
::CGContextRelease(cgBuffer);
::DisposeGWorld(gWorld);
nativeDraw.EndNativeDrawing();
#pragma clang diagnostic warning "-Wdeprecated-declarations"
#elif defined(XP_UNIX)
/* 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 defined(XP_UNIX) || defined(XP_MACOSX)
// Doesn't work in a thebes world, or on OS X.
(void)window;
(void)npprint;
#elif defined(XP_WIN)
/* On Windows, we use the win32 printing surface to print. This, in
@ -1861,15 +1695,6 @@ nsPluginFrame::HandleEvent(nsPresContext* aPresContext,
return fm->FocusPlugin(GetContent());
}
#ifdef XP_MACOSX
if (anEvent->message == NS_PLUGIN_RESOLUTION_CHANGED) {
double scaleFactor = 1.0;
mInstanceOwner->GetContentsScaleFactor(&scaleFactor);
mInstanceOwner->ContentsScaleFactorChanged(scaleFactor);
return NS_OK;
}
#endif
if (mInstanceOwner->SendNativeEvents() &&
anEvent->IsNativeEventDelivererForPlugin()) {
*anEventStatus = mInstanceOwner->ProcessEvent(*anEvent);
@ -2034,14 +1859,8 @@ nsPluginFrame::EndSwapDocShells(nsISupports* aSupports, void*)
}
}
#ifdef XP_MACOSX
if (objectFrame->mWidget) {
objectFrame->RegisterPluginForGeometryUpdates();
}
#else
objectFrame->RegisterPluginForGeometryUpdates();
#endif
}
nsIFrame*
NS_NewObjectFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)

View File

@ -138,6 +138,11 @@ public:
configuration->mClipRegion = mNextConfigurationClipRegion;
}
}
nsIntRect GetWidgetlessClipRect() {
return RegionFromArray(mNextConfigurationClipRegion).GetBounds();
}
/**
* Called after all widget position/size/clip regions have been changed
* (even if there isn't a widget for this plugin).
@ -258,6 +263,15 @@ private:
// stored in mRootPresContextRegisteredWith.
void UnregisterPluginForGeometryUpdates();
static const nsIntRegion RegionFromArray(const nsTArray<nsIntRect>& aRects)
{
nsIntRegion region;
for (uint32_t i = 0; i < aRects.Length(); ++i) {
region.Or(region, aRects[i]);
}
return region;
}
class PluginEventNotifier : public nsRunnable {
public:
explicit PluginEventNotifier(const nsString &aEventType) :

View File

@ -1,37 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// We can use Carbon in this header but not Cocoa. Cocoa pointers must be void.
#ifndef __LP64__
#import <Carbon/Carbon.h>
#endif
#include "nsIWidget.h"
#include "npapi.h"
struct nsRect;
// We use void pointers to avoid exporting native event types to cross-platform code.
#ifndef __LP64__
// Get the rect for an entire top-level Carbon window in screen coords.
void NS_NPAPI_CarbonWindowFrame(WindowRef aWindow, nsRect& outRect);
#endif
// Get the rect for an entire top-level Cocoa window in screen coords.
void NS_NPAPI_CocoaWindowFrame(void* aWindow, nsRect& outRect);
// Returns whether or not a Cocoa NSWindow has main status.
bool NS_NPAPI_CocoaWindowIsMain(void* aWindow);
// 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);

View File

@ -1,207 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsPluginUtilsOSX.h"
#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
#include "nsObjCExceptions.h"
#ifndef __LP64__
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;
}
#endif
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;
}
bool NS_NPAPI_CocoaWindowIsMain(void* aWindow)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
if (!aWindow)
return true;
NSWindow* window = (NSWindow*)aWindow;
return (bool)[window isMainWindow];
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(true);
}
NPError NS_NPAPI_ShowCocoaContextMenu(void* menu, nsIWidget* widget, NPCocoaEvent* event)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
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) {
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;
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NPERR_GENERIC_ERROR);
}
NPBool NS_NPAPI_ConvertPointCocoa(void* inView,
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
double *destX, double *destY, NPCoordinateSpace destSpace)
{
// Plugins don't always have a view/frame. It would be odd to ask for a point conversion
// without a view, so we'll warn about it, but it's technically OK.
if (!inView) {
NS_WARNING("Must have a native view to convert coordinates.");
return false;
}
// Caller has to want a result.
if (!destX && !destY)
return false;
if (sourceSpace == destSpace) {
if (destX)
*destX = sourceX;
if (destY)
*destY = sourceY;
return 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 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 false;
}
if (destX)
*destX = destPoint.x;
if (destY)
*destY = destPoint.y;
return true;
}

View File

@ -1259,3 +1259,24 @@ nsSubDocumentFrame::ObtainIntrinsicSizeFrame()
}
return nullptr;
}
nsIntPoint
nsSubDocumentFrame::GetChromeDisplacement()
{
nsIFrame* nextFrame = nsLayoutUtils::GetCrossDocParentFrame(this);
if (!nextFrame) {
NS_WARNING("Couldn't find window chrome to calculate displacement to.");
return nsIntPoint();
}
nsIFrame* rootFrame = nextFrame;
while (nextFrame) {
rootFrame = nextFrame;
nextFrame = nsLayoutUtils::GetCrossDocParentFrame(rootFrame);
}
nsPoint offset = GetOffsetToCrossDoc(rootFrame);
int32_t appUnitsPerDevPixel = rootFrame->PresContext()->AppUnitsPerDevPixel();
return nsIntPoint((int)(offset.x/appUnitsPerDevPixel),
(int)(offset.y/appUnitsPerDevPixel));
}

View File

@ -127,6 +127,8 @@ public:
*/
bool PassPointerEventsToChildren();
nsIntPoint GetChromeDisplacement();
protected:
friend class AsyncFrameInit;

View File

@ -755,8 +755,7 @@ nsViewManager::DispatchEvent(WidgetGUIEvent *aEvent,
(dispatchUsingCoordinates || aEvent->HasKeyEventMessage() ||
aEvent->IsIMERelatedEvent() ||
aEvent->IsNonRetargetedNativeEventDelivererForPlugin() ||
aEvent->HasPluginActivationEventMessage() ||
aEvent->message == NS_PLUGIN_RESOLUTION_CHANGED)) {
aEvent->HasPluginActivationEventMessage())) {
while (view && !view->GetFrame()) {
view = view->GetParent();
}

View File

@ -65,11 +65,6 @@
#define NS_MOZ_USER_IDLE (NS_WINDOW_START + 67)
#define NS_MOZ_USER_ACTIVE (NS_WINDOW_START + 68)
// The resolution at which a plugin should draw has changed, for
// example as the result of changing from a HiDPI mode to a non-
// HiDPI mode.
#define NS_PLUGIN_RESOLUTION_CHANGED (NS_WINDOW_START + 69)
#define NS_LANGUAGECHANGE (NS_WINDOW_START + 70)
#define NS_MOUSE_MESSAGE_START 300

View File

@ -830,6 +830,28 @@ PuppetWidget::GetNativeData(uint32_t aDataType)
return nullptr;
}
nsIntPoint
PuppetWidget::GetChromeDimensions()
{
if (!GetOwningTabChild()) {
NS_WARNING("PuppetWidget without Tab does not have chrome information.");
return nsIntPoint();
}
return GetOwningTabChild()->GetChromeDisplacement();
}
nsIntPoint
PuppetWidget::GetWindowPosition()
{
if (!GetOwningTabChild()) {
return nsIntPoint();
}
int32_t winX, winY, winW, winH;
NS_ENSURE_SUCCESS(GetOwningTabChild()->GetDimensions(0, &winX, &winY, &winW, &winH), nsIntPoint());
return nsIntPoint(winX, winY);
}
PuppetScreen::PuppetScreen(void *nativeScreen)
{
}
@ -846,6 +868,13 @@ ScreenConfig()
return config;
}
nsIntSize
PuppetWidget::GetScreenDimensions()
{
nsIntRect r = ScreenConfig().rect();
return nsIntSize(r.width, r.height);
}
NS_IMETHODIMP
PuppetScreen::GetId(uint32_t *outId)
{

View File

@ -193,6 +193,14 @@ public:
mDefaultScale = -1;
}
nsIntSize GetScreenDimensions();
// Get the size of the chrome of the window that this tab belongs to.
nsIntPoint GetChromeDimensions();
// Get the screen position of the application window.
nsIntPoint GetWindowPosition();
protected:
bool mEnabled;
bool mVisible;

View File

@ -97,6 +97,10 @@ public:
, mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
, mNativeKeyEvent(nullptr)
, mUniqueId(0)
#ifdef XP_MACOSX
, mNativeKeyCode(0)
, mNativeModifierFlags(0)
#endif
{
}
@ -151,6 +155,14 @@ public:
// over long periods.
uint32_t mUniqueId;
#ifdef XP_MACOSX
// Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
uint16_t mNativeKeyCode;
uint32_t mNativeModifierFlags;
nsString mNativeCharacters;
nsString mNativeCharactersIgnoringModifiers;
#endif
void GetDOMKeyName(nsAString& aKeyName)
{
if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {

View File

@ -191,8 +191,7 @@ WidgetEvent::IsUsingCoordinates() const
return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
!HasPluginActivationEventMessage() &&
!IsNativeEventDelivererForPlugin() &&
!IsContentCommandEvent() &&
message != NS_PLUGIN_RESOLUTION_CHANGED;
!IsContentCommandEvent();
}
bool

View File

@ -28,23 +28,19 @@
#ifndef ComplexTextInputPanel_h_
#define ComplexTextInputPanel_h_
#import <Cocoa/Cocoa.h>
#include "nsString.h"
#include "npapi.h"
@interface ComplexTextInputPanel : NSPanel {
NSTextView *mInputTextView;
}
class ComplexTextInputPanel
{
public:
static ComplexTextInputPanel* GetSharedComplexTextInputPanel();
virtual void PlacePanel(int32_t x, int32_t y) = 0; // Bottom left coordinate of plugin in screen coords
virtual void InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText) = 0;
virtual bool IsInComposition() = 0;
+ (ComplexTextInputPanel*)sharedComplexTextInputPanel;
- (NSTextInputContext*)inputContext;
- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
- (void)cancelComposition;
- (BOOL)inComposition;
// This places the text input panel fully onscreen and below the lower left
// corner of the focused plugin.
- (void)adjustTo:(NSView*)view;
@end
protected:
virtual ~ComplexTextInputPanel() {};
};
#endif // ComplexTextInputPanel_h_

View File

@ -27,6 +27,8 @@
#import "ComplexTextInputPanel.h"
#import <Cocoa/Cocoa.h>
#include <algorithm>
#include "mozilla/Preferences.h"
#include "nsChildView.h"
@ -34,16 +36,35 @@
using namespace mozilla;
extern "C" OSStatus TSMProcessRawKeyEvent(EventRef anEvent);
#define kInputWindowHeight 20
@implementation ComplexTextInputPanel
@interface ComplexTextInputPanelImpl : NSPanel {
NSTextView *mInputTextView;
}
+ (ComplexTextInputPanel*)sharedComplexTextInputPanel
+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl;
- (NSTextInputContext*)inputContext;
- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string;
- (void)cancelComposition;
- (BOOL)inComposition;
// This places the text input panel fully onscreen and below the lower left
// corner of the focused plugin.
- (void)adjustTo:(NSPoint)point;
@end
@implementation ComplexTextInputPanelImpl
+ (ComplexTextInputPanelImpl*)sharedComplexTextInputPanelImpl
{
static ComplexTextInputPanel *sComplexTextInputPanel;
if (!sComplexTextInputPanel)
sComplexTextInputPanel = [[ComplexTextInputPanel alloc] init];
return sComplexTextInputPanel;
static ComplexTextInputPanelImpl *sComplexTextInputPanelImpl;
if (!sComplexTextInputPanelImpl)
sComplexTextInputPanelImpl = [[ComplexTextInputPanelImpl alloc] init];
return sComplexTextInputPanelImpl;
}
- (id)init
@ -107,31 +128,45 @@ using namespace mozilla;
}
}
- (BOOL)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
- (void)interpretKeyEvent:(NSEvent*)event string:(NSString**)string
{
BOOL hadMarkedText = [mInputTextView hasMarkedText];
*string = nil;
if (![[mInputTextView inputContext] handleEvent:event])
return NO;
if (!nsCocoaFeatures::OnMountainLionOrLater()) {
// This "works" on OS X 10.7 and below, but at the cost of breaking plugin
// IME, even in non-e10s mode: In an IME like Kotoeri Hiragana, every key
// gets sent to the plugin individually.
if (![[mInputTextView inputContext] handleEvent:event]) {
return;
}
} else {
// On OS X 10.8 and above we can't use -[NSTextInputContext handleEvent:]
// -- it doesn't work with a synthesized event. We need to activate the
// input context and call TSMProcessRawKeyEvent instead. This also allows
// plugin IME to work properly in non-e10s mode.
[[mInputTextView inputContext] activate];
OSErr err = TSMProcessRawKeyEvent((EventRef)[event eventRef]);
if (err != noErr) {
return;
}
}
if ([mInputTextView hasMarkedText]) {
// Don't show the input method window for dead keys
if ([[event characters] length] > 0)
if ([[event characters] length] > 0) {
[self orderFront:nil];
return YES;
}
return;
} else {
[self orderOut:nil];
NSString *text = [[mInputTextView textStorage] string];
if ([text length] > 0)
if ([text length] > 0) {
*string = [[text copy] autorelease];
}
}
[mInputTextView setString:@""];
return hadMarkedText;
}
- (NSTextInputContext*)inputContext
@ -150,23 +185,13 @@ using namespace mozilla;
return [mInputTextView hasMarkedText];
}
- (void)adjustTo:(NSView*)view
- (void)adjustTo:(NSPoint)point
{
NSRect viewRect = [view frame];
viewRect.origin.x = 0;
viewRect.origin.y = 0;
viewRect = [view convertRect:viewRect toView:nil];
if (nsCocoaFeatures::OnLionOrLater()) {
viewRect = [[view window] convertRectToScreen:viewRect];
} else {
viewRect.origin = [[view window] convertBaseToScreen:viewRect.origin];
}
NSRect selfRect = [self frame];
CGFloat minWidth = static_cast<CGFloat>(
Preferences::GetUint("ui.plugin.panel.min-width", 500));
NSRect rect = NSMakeRect(viewRect.origin.x,
viewRect.origin.y - selfRect.size.height,
std::max(viewRect.size.width, minWidth),
CGFloat minWidth = static_cast<CGFloat>(Preferences::GetUint("ui.plugin.panel.min-width", 500));
NSRect rect = NSMakeRect(point.x,
point.y - selfRect.size.height,
500,
selfRect.size.height);
// Adjust to screen.
@ -192,3 +217,70 @@ using namespace mozilla;
}
@end
class ComplexTextInputPanelPrivate : public ComplexTextInputPanel
{
public:
ComplexTextInputPanelPrivate();
virtual void InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText);
virtual bool IsInComposition();
virtual void PlacePanel(int32_t x, int32_t y);
private:
~ComplexTextInputPanelPrivate();
ComplexTextInputPanelImpl* mPanel;
};
ComplexTextInputPanelPrivate::ComplexTextInputPanelPrivate()
{
mPanel = [[ComplexTextInputPanelImpl alloc] init];
}
ComplexTextInputPanelPrivate::~ComplexTextInputPanelPrivate()
{
[mPanel release];
}
ComplexTextInputPanel*
ComplexTextInputPanel::GetSharedComplexTextInputPanel()
{
static ComplexTextInputPanelPrivate *sComplexTextInputPanelPrivate;
if (!sComplexTextInputPanelPrivate) {
sComplexTextInputPanelPrivate = new ComplexTextInputPanelPrivate();
}
return sComplexTextInputPanelPrivate;
}
void
ComplexTextInputPanelPrivate::InterpretKeyEvent(NPCocoaEvent* aEvent, nsAString& aOutText)
{
NSEvent* nativeEvent = [NSEvent keyEventWithType:NSKeyDown
location:NSMakePoint(0,0)
modifierFlags:aEvent->data.key.modifierFlags
timestamp:0
windowNumber:[mPanel windowNumber]
context:[mPanel graphicsContext]
characters:(NSString*)aEvent->data.key.characters
charactersIgnoringModifiers:(NSString*)aEvent->data.key.charactersIgnoringModifiers
isARepeat:aEvent->data.key.isARepeat
keyCode:aEvent->data.key.keyCode];
NSString* textString = nil;
[mPanel interpretKeyEvent:nativeEvent string:&textString];
if (textString) {
nsCocoaUtils::GetStringForNSString(textString, aOutText);
}
}
bool
ComplexTextInputPanelPrivate::IsInComposition()
{
return !![mPanel inComposition];
}
void
ComplexTextInputPanelPrivate::PlacePanel(int32_t x, int32_t y)
{
[mPanel adjustTo:NSMakePoint(x, y)];
}

View File

@ -15,7 +15,6 @@
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsITimer.h"
#include "npapi.h"
#include "nsTArray.h"
#include "mozilla/EventForwards.h"
@ -317,9 +316,8 @@ protected:
};
/**
* TextInputHandlerBase is a base class of PluginTextInputHandler,
* IMEInputHandler and TextInputHandler. Utility methods should be implemented
* this level.
* TextInputHandlerBase is a base class of IMEInputHandler and TextInputHandler.
* Utility methods should be implemented this level.
*/
class TextInputHandlerBase
@ -678,151 +676,6 @@ private:
static int32_t sSecureEventInputCount;
};
/**
* PluginTextInputHandler handles text input events for plugins.
*/
class PluginTextInputHandler : public TextInputHandlerBase
{
public:
/**
* When starting complex text input for current event on plugin, this is
* called. See also the comment of StartComplexTextInputForCurrentEvent() of
* nsIPluginWidget.
*/
nsresult StartComplexTextInputForCurrentEvent()
{
mPluginComplexTextInputRequested = true;
return NS_OK;
}
/**
* HandleKeyDownEventForPlugin() handles aNativeKeyEvent.
*
* @param aNativeKeyEvent A native NSKeyDown event.
*/
void HandleKeyDownEventForPlugin(NSEvent* aNativeKeyEvent);
/**
* HandleKeyUpEventForPlugin() handles aNativeKeyEvent.
*
* @param aNativeKeyEvent A native NSKeyUp event.
*/
void HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent);
/**
* ConvertCocoaKeyEventToNPCocoaEvent() converts aCocoaEvent to NPCocoaEvent.
*
* @param aCocoaEvent A native key event.
* @param aPluginEvent The result.
*/
static void ConvertCocoaKeyEventToNPCocoaEvent(NSEvent* aCocoaEvent,
NPCocoaEvent& aPluginEvent);
#ifndef __LP64__
/**
* InstallPluginKeyEventsHandler() is called when initializing process.
* RemovePluginKeyEventsHandler() is called when finalizing process.
* These methods initialize/finalize global resource for handling events for
* plugins.
*/
static void InstallPluginKeyEventsHandler();
static void RemovePluginKeyEventsHandler();
/**
* This must be called before first key/IME event for plugins.
* This method initializes IMKInputSession methods swizzling.
*/
static void SwizzleMethods();
/**
* When a composition starts or finishes, this is called.
*/
void SetPluginTSMInComposition(bool aInComposition)
{
mPluginTSMInComposition = aInComposition;
}
#endif // #ifndef __LP64__
protected:
bool mIgnoreNextKeyUpEvent;
PluginTextInputHandler(nsChildView* aWidget, NSView<mozView> *aNativeView);
~PluginTextInputHandler();
private:
#ifndef __LP64__
TSMDocumentID mPluginTSMDoc;
bool mPluginTSMInComposition;
#endif // #ifndef __LP64__
bool mPluginComplexTextInputRequested;
/**
* DispatchCocoaNPAPITextEvent() dispatches a text event for Cocoa plugin.
*
* @param aString A string inputted by the dispatching event.
* @return TRUE if the dispatched event was consumed.
* Otherwise, FALSE.
*/
bool DispatchCocoaNPAPITextEvent(NSString* aString);
/**
* Whether the plugin is in composition or not.
* On 32bit build, this returns the state of mPluginTSMInComposition.
* On 64bit build, this returns ComplexTextInputPanel's state.
*
* @return TRUE if plugin is in composition. Otherwise,
* FALSE.
*/
bool IsInPluginComposition();
#ifndef __LP64__
/**
* Create a TSM document for use with plugins, so that we can support IME in
* them. Once it's created, if need be (re)activate it. Some plugins (e.g.
* the Flash plugin running in Camino) don't create their own TSM document --
* without which IME can't work. Others (e.g. the Flash plugin running in
* Firefox) create a TSM document that (somehow) makes the input window behave
* badly when it contains more than one kind of input (say Hiragana and
* Romaji). (We can't just use the per-NSView TSM documents that Cocoa
* provides (those created and managed by the NSTSMInputContext class) -- for
* some reason TSMProcessRawKeyEvent() doesn't work with them.)
*/
void ActivatePluginTSMDocument();
/**
* HandleCarbonPluginKeyEvent() handles the aKeyEvent. This is called by
* PluginKeyEventsHandler().
*
* @param aKeyEvent A native Carbon event.
*/
void HandleCarbonPluginKeyEvent(EventRef aKeyEvent);
/**
* Target for text services events sent as the result of calls made to
* TSMProcessRawKeyEvent() in HandleKeyDownEventForPlugin() when a plugin has
* the focus. The calls to TSMProcessRawKeyEvent() short-circuit Cocoa-based
* IME (which would otherwise interfere with our efforts) and allow Carbon-
* based IME to work in plugins (via the NPAPI). This strategy doesn't cause
* trouble for plugins that (like the Java Embedding Plugin) bypass the NPAPI
* to get their keyboard events and do their own Cocoa-based IME.
*/
static OSStatus PluginKeyEventsHandler(EventHandlerCallRef aHandlerRef,
EventRef aEvent,
void *aUserData);
static EventHandlerRef sPluginKeyEventsHandler;
#endif // #ifndef __LP64__
};
/**
* IMEInputHandler manages:
* 1. The IME/keyboard layout statement of nsChildView.
@ -836,7 +689,7 @@ private:
* actual focused view is notified by OnFocusChangeInGecko.
*/
class IMEInputHandler : public PluginTextInputHandler
class IMEInputHandler : public TextInputHandlerBase
{
public:
virtual bool OnDestroyWidget(nsChildView* aDestroyingWidget);

View File

@ -22,34 +22,6 @@
#include "WidgetUtils.h"
#include "nsPrintfCString.h"
#ifdef __LP64__
#include "ComplexTextInputPanel.h"
#include <objc/runtime.h>
#endif // __LP64__
#ifndef __LP64__
enum {
// Currently focused ChildView (while this TSM document is active).
// Transient (only set while TSMProcessRawKeyEvent() is processing a key
// event), and the ChildView will be retained and released around the call
// to TSMProcessRawKeyEvent() -- so it can be weak.
kFocusedChildViewTSMDocPropertyTag = 'GKFV', // type ChildView* [WEAK]
};
// Undocumented HIToolbox function used by WebKit to allow Carbon-based IME
// to work in a Cocoa-based browser (like Safari or Cocoa-widgets Firefox).
// (Recent WebKit versions actually use a thin wrapper around this function
// called WKSendKeyEventToTSM().)
//
// Calling TSMProcessRawKeyEvent() from ChildView's keyDown: and keyUp:
// methods (when the ChildView is a plugin view) bypasses Cocoa's IME
// infrastructure and (instead) causes Carbon TSM events to be sent on each
// NSKeyDown event. We install a Carbon event handler
// (PluginKeyEventsHandler()) to catch these events and pass them to Gecko
// (which in turn passes them to the plugin).
extern "C" long TSMProcessRawKeyEvent(EventRef carbonEvent);
#endif // __LP64__
using namespace mozilla;
using namespace mozilla::widget;
@ -804,6 +776,22 @@ TISInputSourceWrapper::InitKeyEvent(NSEvent *aNativeKeyEvent,
// call), so there is no need to retain and release this data.
aKeyEvent.mNativeKeyEvent = aNativeKeyEvent;
// Fill in fields used for Cocoa NPAPI plugins
if ([aNativeKeyEvent type] == NSKeyDown ||
[aNativeKeyEvent type] == NSKeyUp) {
aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
nsAutoString nativeChars;
nsCocoaUtils::GetStringForNSString([aNativeKeyEvent characters], nativeChars);
aKeyEvent.mNativeCharacters.Assign(nativeChars);
nsAutoString nativeCharsIgnoringModifiers;
nsCocoaUtils::GetStringForNSString([aNativeKeyEvent charactersIgnoringModifiers], nativeCharsIgnoringModifiers);
aKeyEvent.mNativeCharactersIgnoringModifiers.Assign(nativeCharsIgnoringModifiers);
} else if ([aNativeKeyEvent type] == NSFlagsChanged) {
aKeyEvent.mNativeKeyCode = [aNativeKeyEvent keyCode];
aKeyEvent.mNativeModifierFlags = [aNativeKeyEvent modifierFlags];
}
aKeyEvent.refPoint = LayoutDeviceIntPoint(0, 0);
// If a keyboard layout override is set, we also need to force the keyboard
@ -1641,17 +1629,12 @@ TextInputHandler::HandleKeyUpEvent(NSEvent* aNativeEvent)
("%p TextInputHandler::HandleKeyUpEvent, aNativeEvent=%p, "
"type=%s, keyCode=%lld (0x%X), modifierFlags=0x%X, characters=\"%s\", "
"charactersIgnoringModifiers=\"%s\", "
"mIgnoreNextKeyUpEvent=%s, IsIMEComposing()=%s",
"IsIMEComposing()=%s",
this, aNativeEvent, GetNativeKeyEventType(aNativeEvent),
[aNativeEvent keyCode], [aNativeEvent keyCode],
[aNativeEvent modifierFlags], GetCharacters([aNativeEvent characters]),
GetCharacters([aNativeEvent charactersIgnoringModifiers]),
TrueOrFalse(mIgnoreNextKeyUpEvent), TrueOrFalse(IsIMEComposing())));
if (mIgnoreNextKeyUpEvent) {
mIgnoreNextKeyUpEvent = false;
return;
}
TrueOrFalse(IsIMEComposing())));
if (Destroyed()) {
PR_LOG(gLog, PR_LOG_ALWAYS,
@ -2011,19 +1994,19 @@ TextInputHandler::DispatchKeyEventForFlagsChanged(NSEvent* aNativeEvent,
uint32_t message = aDispatchKeyDown ? NS_KEY_DOWN : NS_KEY_UP;
NPCocoaEvent cocoaEvent;
// Fire a key event.
WidgetKeyboardEvent keyEvent(true, message, mWidget);
InitKeyEvent(aNativeEvent, keyEvent);
// create event for use by plugins
if ([mView isPluginView]) {
if ([mView pluginEventModel] == NPEventModelCocoa) {
ConvertCocoaKeyEventToNPCocoaEvent(aNativeEvent, cocoaEvent);
// Attach a plugin event, in case keyEvent gets dispatched to a plugin. Only
// one field is needed -- the type. The other fields can be constructed as
// the need arises. But Gecko doesn't have anything equivalent to the
// NPCocoaEventFlagsChanged type, and this needs to be passed accurately to
// any plugin to which this event is sent.
NPCocoaEvent cocoaEvent;
nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent);
cocoaEvent.type = NPCocoaEventFlagsChanged;
keyEvent.mPluginEvent.Copy(cocoaEvent);
}
}
DispatchEvent(keyEvent);
@ -3239,7 +3222,7 @@ IMEInputHandler::GetValidAttributesForMarkedText()
IMEInputHandler::IMEInputHandler(nsChildView* aWidget,
NSView<mozView> *aNativeView) :
PluginTextInputHandler(aWidget, aNativeView),
TextInputHandlerBase(aWidget, aNativeView),
mPendingMethods(0), mIMECompositionString(nullptr),
mIsIMEComposing(false), mIsIMEEnabled(true),
mIsASCIICapableOnly(false), mIgnoreIMECommit(false),
@ -3307,10 +3290,6 @@ IMEInputHandler::OnDestroyWidget(nsChildView* aDestroyingWidget)
sFocusedIMEHandler->OnDestroyWidget(aDestroyingWidget);
}
if (!PluginTextInputHandler::OnDestroyWidget(aDestroyingWidget)) {
return false;
}
if (IsIMEComposing()) {
// If our view is in the composition, we should clean up it.
CancelIMEComposition();
@ -3631,587 +3610,6 @@ IMEInputHandler::OpenSystemPreferredLanguageIME()
#pragma mark -
/******************************************************************************
*
* PluginTextInputHandler implementation
*
******************************************************************************/
PluginTextInputHandler::PluginTextInputHandler(nsChildView* aWidget,
NSView<mozView> *aNativeView) :
TextInputHandlerBase(aWidget, aNativeView),
mIgnoreNextKeyUpEvent(false),
#ifndef __LP64__
mPluginTSMDoc(0), mPluginTSMInComposition(false),
#endif // #ifndef __LP64__
mPluginComplexTextInputRequested(false)
{
}
PluginTextInputHandler::~PluginTextInputHandler()
{
#ifndef __LP64__
if (mPluginTSMDoc) {
::DeleteTSMDocument(mPluginTSMDoc);
}
#endif // #ifndef __LP64__
}
/* static */ void
PluginTextInputHandler::ConvertCocoaKeyEventToNPCocoaEvent(
NSEvent* aCocoaEvent,
NPCocoaEvent& aPluginEvent)
{
nsCocoaUtils::InitNPCocoaEvent(&aPluginEvent);
NSEventType nativeType = [aCocoaEvent type];
switch (nativeType) {
case NSKeyDown:
aPluginEvent.type = NPCocoaEventKeyDown;
break;
case NSKeyUp:
aPluginEvent.type = NPCocoaEventKeyUp;
break;
case NSFlagsChanged:
aPluginEvent.type = NPCocoaEventFlagsChanged;
break;
default:
NS_WARNING("Asked to convert key event of unknown type to Cocoa plugin event!");
}
aPluginEvent.data.key.modifierFlags = [aCocoaEvent modifierFlags];
aPluginEvent.data.key.keyCode = [aCocoaEvent keyCode];
// don't try to access character data for flags changed events,
// it will raise an exception
if (nativeType != NSFlagsChanged) {
aPluginEvent.data.key.characters = (NPNSString*)[aCocoaEvent characters];
aPluginEvent.data.key.charactersIgnoringModifiers =
(NPNSString*)[aCocoaEvent charactersIgnoringModifiers];
aPluginEvent.data.key.isARepeat = [aCocoaEvent isARepeat];
}
}
#ifndef __LP64__
EventHandlerRef PluginTextInputHandler::sPluginKeyEventsHandler = NULL;
/* static */ void
PluginTextInputHandler::InstallPluginKeyEventsHandler()
{
if (sPluginKeyEventsHandler) {
return;
}
static const EventTypeSpec sTSMEvents[] =
{ { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } };
::InstallEventHandler(::GetEventDispatcherTarget(),
::NewEventHandlerUPP(PluginKeyEventsHandler),
GetEventTypeCount(sTSMEvents),
sTSMEvents,
NULL,
&sPluginKeyEventsHandler);
}
/* static */ void
PluginTextInputHandler::RemovePluginKeyEventsHandler()
{
if (!sPluginKeyEventsHandler) {
return;
}
::RemoveEventHandler(sPluginKeyEventsHandler);
sPluginKeyEventsHandler = NULL;
}
/* static */ void
PluginTextInputHandler::SwizzleMethods()
{
Class IMKInputSessionClass = ::NSClassFromString(@"IMKInputSession");
nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(handleEvent:),
@selector(PluginTextInputHandler_IMKInputSession_handleEvent:));
nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(commitComposition),
@selector(PluginTextInputHandler_IMKInputSession_commitComposition));
nsToolkit::SwizzleMethods(IMKInputSessionClass, @selector(finishSession),
@selector(PluginTextInputHandler_IMKInputSession_finishSession));
}
/* static */ OSStatus
PluginTextInputHandler::PluginKeyEventsHandler(EventHandlerCallRef aHandlerRef,
EventRef aEvent,
void *aUserData)
{
nsAutoreleasePool localPool;
TSMDocumentID activeDoc = ::TSMGetActiveDocument();
NS_ENSURE_TRUE(activeDoc, eventNotHandledErr);
ChildView *target = nil;
OSStatus status = ::TSMGetDocumentProperty(activeDoc,
kFocusedChildViewTSMDocPropertyTag,
sizeof(ChildView *), nil, &target);
NS_ENSURE_TRUE(status == noErr, eventNotHandledErr);
NS_ENSURE_TRUE(target, eventNotHandledErr);
EventRef keyEvent = NULL;
status = ::GetEventParameter(aEvent, kEventParamTextInputSendKeyboardEvent,
typeEventRef, NULL, sizeof(EventRef), NULL,
&keyEvent);
NS_ENSURE_TRUE(status == noErr, eventNotHandledErr);
NS_ENSURE_TRUE(keyEvent, eventNotHandledErr);
nsIWidget* widget = [target widget];
NS_ENSURE_TRUE(widget, eventNotHandledErr);
TextInputHandler* handler =
static_cast<nsChildView*>(widget)->GetTextInputHandler();
NS_ENSURE_TRUE(handler, eventNotHandledErr);
handler->HandleCarbonPluginKeyEvent(keyEvent);
return noErr;
}
// Called from PluginKeyEventsHandler() (a handler for Carbon TSM events) to
// process a Carbon key event for the currently focused plugin. Both Unicode
// characters and "Mac encoding characters" (in the MBCS or "multibyte
// character system") are (or should be) available from aKeyEvent, but here we
// use the MCBS characters. This is how the WebKit does things, and seems to
// be what plugins expect.
void
PluginTextInputHandler::HandleCarbonPluginKeyEvent(EventRef aKeyEvent)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (Destroyed()) {
return;
}
NS_ASSERTION(mView, "mView must not be NULL");
nsRefPtr<nsChildView> kungFuDeathGrip(mWidget);
if ([mView pluginEventModel] == NPEventModelCocoa) {
UInt32 size;
OSStatus status =
::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes, typeUnicodeText,
NULL, 0, &size, NULL);
NS_ENSURE_TRUE(status == noErr, );
UniChar* chars = (UniChar*)malloc(size);
NS_ENSURE_TRUE(chars, );
status = ::GetEventParameter(aKeyEvent, kEventParamKeyUnicodes,
typeUnicodeText, NULL, size, NULL, chars);
if (status != noErr) {
free(chars);
return;
}
CFStringRef text =
::CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, chars,
(size / sizeof(UniChar)),
kCFAllocatorNull);
if (!text) {
free(chars);
return;
}
NPCocoaEvent cocoaTextEvent;
nsCocoaUtils::InitNPCocoaEvent(&cocoaTextEvent);
cocoaTextEvent.type = NPCocoaEventTextInput;
cocoaTextEvent.data.text.text = (NPNSString*)text;
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaTextEvent);
DispatchEvent(pluginEvent);
::CFRelease(text);
free(chars);
return;
}
UInt32 numCharCodes;
OSStatus status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
typeChar, NULL, 0, &numCharCodes, NULL);
NS_ENSURE_TRUE(status == noErr, );
nsAutoTArray<unsigned char, 3> charCodes;
charCodes.SetLength(numCharCodes);
status = ::GetEventParameter(aKeyEvent, kEventParamKeyMacCharCodes,
typeChar, NULL, numCharCodes, NULL,
charCodes.Elements());
NS_ENSURE_TRUE(status == noErr, );
UInt32 modifiers;
status = ::GetEventParameter(aKeyEvent, kEventParamKeyModifiers,
typeUInt32, NULL, sizeof(modifiers), NULL,
&modifiers);
NS_ENSURE_TRUE(status == noErr, );
NSUInteger cocoaModifiers = 0;
if (modifiers & shiftKey) {
cocoaModifiers |= NSShiftKeyMask;
}
if (modifiers & controlKey) {
cocoaModifiers |= NSControlKeyMask;
}
if (modifiers & optionKey) {
cocoaModifiers |= NSAlternateKeyMask;
}
if (modifiers & cmdKey) { // Should never happen
cocoaModifiers |= NSCommandKeyMask;
}
UInt32 macKeyCode;
status = ::GetEventParameter(aKeyEvent, kEventParamKeyCode,
typeUInt32, NULL, sizeof(macKeyCode), NULL,
&macKeyCode);
NS_ENSURE_TRUE(status == noErr, );
TISInputSourceWrapper& currentInputSource =
TISInputSourceWrapper::CurrentInputSource();
EventRef cloneEvent = ::CopyEvent(aKeyEvent);
for (uint32_t i = 0; i < numCharCodes; ++i) {
status = ::SetEventParameter(cloneEvent, kEventParamKeyMacCharCodes,
typeChar, 1, charCodes.Elements() + i);
NS_ENSURE_TRUE(status == noErr, );
EventRecord eventRec;
if (::ConvertEventRefToEventRecord(cloneEvent, &eventRec)) {
WidgetKeyboardEvent keydownEvent(true, NS_KEY_DOWN, mWidget);
nsCocoaUtils::InitInputEvent(keydownEvent, cocoaModifiers);
uint32_t keyCode =
currentInputSource.ComputeGeckoKeyCode(macKeyCode, ::LMGetKbdType(),
keydownEvent.IsMeta());
uint32_t charCode(charCodes.ElementAt(i));
keydownEvent.time = PR_IntervalNow();
keydownEvent.mPluginEvent.Copy(eventRec);
if (IsSpecialGeckoKey(macKeyCode)) {
keydownEvent.keyCode = keyCode;
} else {
// XXX This is wrong. charCode must be 0 for keydown event.
keydownEvent.charCode = charCode;
keydownEvent.isChar = true;
}
DispatchEvent(keydownEvent);
if (Destroyed()) {
break;
}
}
}
::ReleaseEvent(cloneEvent);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void
PluginTextInputHandler::ActivatePluginTSMDocument()
{
if (!mPluginTSMDoc) {
// Create a TSM document that supports both non-Unicode and Unicode input.
// Though ProcessPluginKeyEvent() only sends Mac char codes to
// the plugin, this makes the input window behave better when it contains
// more than one kind of input (say Hiragana and Romaji). This is what
// the OS does when it creates a TSM document for use by an
// NSTSMInputContext class.
InterfaceTypeList supportedServices;
supportedServices[0] = kTextServiceDocumentInterfaceType;
supportedServices[1] = kUnicodeDocumentInterfaceType;
::NewTSMDocument(2, supportedServices, &mPluginTSMDoc, 0);
// We'll need to use the "input window".
::UseInputWindow(mPluginTSMDoc, YES);
::ActivateTSMDocument(mPluginTSMDoc);
} else if (::TSMGetActiveDocument() != mPluginTSMDoc) {
::ActivateTSMDocument(mPluginTSMDoc);
}
}
#endif // #ifndef __LP64__
void
PluginTextInputHandler::HandleKeyDownEventForPlugin(NSEvent* aNativeKeyEvent)
{
if (Destroyed()) {
return;
}
NS_ASSERTION(mView, "mView must not be NULL");
#ifdef __LP64__
if ([mView pluginEventModel] != NPEventModelCocoa) {
return;
}
ComplexTextInputPanel* ctiPanel =
[ComplexTextInputPanel sharedComplexTextInputPanel];
[ctiPanel adjustTo:mView];
// If a composition is in progress then simply let the input panel continue
// it.
if (IsInPluginComposition()) {
// Don't send key up events for key downs associated with compositions.
mIgnoreNextKeyUpEvent = true;
NSString* textString = nil;
[ctiPanel interpretKeyEvent:aNativeKeyEvent string:&textString];
if (textString) {
DispatchCocoaNPAPITextEvent(textString);
}
return;
}
// Reset complex text input request flag.
mPluginComplexTextInputRequested = false;
// Send key down event to the plugin.
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
NPCocoaEvent cocoaEvent;
ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, cocoaEvent);
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
DispatchEvent(pluginEvent);
if (Destroyed()) {
return;
}
// Start complex text composition if requested.
if (mPluginComplexTextInputRequested) {
// Don't send key up events for key downs associated with compositions.
mIgnoreNextKeyUpEvent = true;
NSString* textString = nil;
[ctiPanel interpretKeyEvent:aNativeKeyEvent string:&textString];
if (textString) {
DispatchCocoaNPAPITextEvent(textString);
}
}
#else // #ifdef __LP64__
bool wasInComposition = false;
if ([mView pluginEventModel] == NPEventModelCocoa) {
if (IsInPluginComposition()) {
wasInComposition = true;
// Don't send key up events for key downs associated with compositions.
mIgnoreNextKeyUpEvent = true;
} else {
// Reset complex text input request flag.
mPluginComplexTextInputRequested = false;
// Send key down event to the plugin.
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
NPCocoaEvent cocoaEvent;
ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, cocoaEvent);
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent);
DispatchEvent(pluginEvent);
if (Destroyed()) {
return;
}
// Only continue if plugin wants complex text input.
if (!mPluginComplexTextInputRequested) {
return;
}
// Don't send key up events for key downs associated with compositions.
mIgnoreNextKeyUpEvent = true;
}
// Don't send complex text input to a plugin in Cocoa event mode if
// either the Control key or the Command key is pressed -- even if the
// plugin has requested it, or we are already in IME composition. This
// conforms to our behavior in 64-bit mode and fixes bug 619217.
NSUInteger modifierFlags = [aNativeKeyEvent modifierFlags];
if ((modifierFlags & NSControlKeyMask) ||
(modifierFlags & NSCommandKeyMask)) {
return;
}
}
// This will take care of all Carbon plugin events and also send Cocoa plugin
// text events when NSInputContext is not available (ifndef NP_NO_CARBON).
ActivatePluginTSMDocument();
// We use the active TSM document to pass a pointer to ourselves (the
// currently focused ChildView) to PluginKeyEventsHandler(). Because this
// pointer is weak, we should retain and release ourselves around the call
// to TSMProcessRawKeyEvent().
nsAutoRetainCocoaObject kungFuDeathGrip(mView);
::TSMSetDocumentProperty(mPluginTSMDoc,
kFocusedChildViewTSMDocPropertyTag,
sizeof(ChildView *), &mView);
::TSMProcessRawKeyEvent([aNativeKeyEvent _eventRef]);
::TSMRemoveDocumentProperty(mPluginTSMDoc,
kFocusedChildViewTSMDocPropertyTag);
#endif // #ifdef __LP64__ else
}
void
PluginTextInputHandler::HandleKeyUpEventForPlugin(NSEvent* aNativeKeyEvent)
{
if (mIgnoreNextKeyUpEvent) {
mIgnoreNextKeyUpEvent = false;
return;
}
if (Destroyed()) {
return;
}
NS_ASSERTION(mView, "mView must not be NULL");
NPEventModel eventModel = [mView pluginEventModel];
if (eventModel == NPEventModelCocoa) {
// Don't send key up events to Cocoa plugins during composition.
if (IsInPluginComposition()) {
return;
}
WidgetKeyboardEvent keyupEvent(true, NS_KEY_UP, mWidget);
InitKeyEvent(aNativeKeyEvent, keyupEvent);
NPCocoaEvent pluginEvent;
ConvertCocoaKeyEventToNPCocoaEvent(aNativeKeyEvent, pluginEvent);
keyupEvent.mPluginEvent.Copy(pluginEvent);
DispatchEvent(keyupEvent);
return;
}
}
bool
PluginTextInputHandler::IsInPluginComposition()
{
return
#ifdef __LP64__
[[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition] != NO;
#else // #ifdef __LP64__
mPluginTSMInComposition;
#endif // #ifdef __LP64__ else
}
bool
PluginTextInputHandler::DispatchCocoaNPAPITextEvent(NSString* aString)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
NPCocoaEvent cocoaTextEvent;
nsCocoaUtils::InitNPCocoaEvent(&cocoaTextEvent);
cocoaTextEvent.type = NPCocoaEventTextInput;
cocoaTextEvent.data.text.text = (NPNSString*)aString;
WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, mWidget);
nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaTextEvent);
return DispatchEvent(pluginEvent);
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
}
#pragma mark -
#ifndef __LP64__
/******************************************************************************
*
* PluginTextInputHandler_IMKInputSession_* implementation
*
******************************************************************************/
// IMKInputSession is an undocumented class in the HIToolbox framework. It's
// present on both Leopard and SnowLeopard, and is used at a low level to
// process IME input regardless of which high-level API is used (Text Services
// Manager or Cocoa). It works the same way in both 32-bit and 64-bit code.
@interface NSObject (IMKInputSessionMethodSwizzling)
- (BOOL)PluginTextInputHandler_IMKInputSession_handleEvent:(EventRef)theEvent;
- (void)PluginTextInputHandler_IMKInputSession_commitComposition;
- (void)PluginTextInputHandler_IMKInputSession_finishSession;
@end
@implementation NSObject (IMKInputSessionMethodSwizzling)
- (BOOL)PluginTextInputHandler_IMKInputSession_handleEvent:(EventRef)theEvent
{
[self retain];
BOOL retval =
[self PluginTextInputHandler_IMKInputSession_handleEvent:theEvent];
NSUInteger retainCount = [self retainCount];
[self release];
// Return without doing anything if we've been deleted.
if (retainCount == 1) {
return retval;
}
NSWindow *mainWindow = [NSApp mainWindow];
NSResponder *firstResponder = [mainWindow firstResponder];
if (![firstResponder isKindOfClass:[ChildView class]]) {
return retval;
}
// 'charactersEntered' is the length (in bytes) of currently "marked text"
// -- text that's been entered in IME but not yet committed. If it's
// non-zero we're composing text in an IME session; if it's zero we're
// not in an IME session.
NSInteger entered = 0;
object_getInstanceVariable(self, "charactersEntered",
(void **) &entered);
nsIWidget* widget = [(ChildView*)firstResponder widget];
NS_ENSURE_TRUE(widget, retval);
TextInputHandler* handler =
static_cast<nsChildView*>(widget)->GetTextInputHandler();
NS_ENSURE_TRUE(handler, retval);
handler->SetPluginTSMInComposition(entered != 0);
return retval;
}
// This method is called whenever IME input is committed as a result of an
// "abnormal" termination -- for example when changing the keyboard focus from
// one input field to another.
- (void)PluginTextInputHandler_IMKInputSession_commitComposition
{
NSWindow *mainWindow = [NSApp mainWindow];
NSResponder *firstResponder = [mainWindow firstResponder];
if ([firstResponder isKindOfClass:[ChildView class]]) {
nsIWidget* widget = [(ChildView*)firstResponder widget];
if (widget) {
TextInputHandler* handler =
static_cast<nsChildView*>(widget)->GetTextInputHandler();
if (handler) {
handler->SetPluginTSMInComposition(false);
}
}
}
[self PluginTextInputHandler_IMKInputSession_commitComposition];
}
// This method is called just before we're deallocated.
- (void)PluginTextInputHandler_IMKInputSession_finishSession
{
NSWindow *mainWindow = [NSApp mainWindow];
NSResponder *firstResponder = [mainWindow firstResponder];
if ([firstResponder isKindOfClass:[ChildView class]]) {
nsIWidget* widget = [(ChildView*)firstResponder widget];
if (widget) {
TextInputHandler* handler =
static_cast<nsChildView*>(widget)->GetTextInputHandler();
if (handler) {
handler->SetPluginTSMInComposition(false);
}
}
}
[self PluginTextInputHandler_IMKInputSession_finishSession];
}
@end
#endif // #ifndef __LP64__
#pragma mark -
/******************************************************************************
*
* TextInputHandlerBase implementation

View File

@ -18,6 +18,7 @@ EXPORTS += [
]
UNIFIED_SOURCES += [
'ComplexTextInputPanel.mm',
'GfxInfo.mm',
'NativeKeyBindings.mm',
'nsAppShell.mm',
@ -65,11 +66,6 @@ SOURCES += [
'nsClipboard.mm',
]
if CONFIG['TARGET_CPU'] == 'x86_64':
UNIFIED_SOURCES += [
'ComplexTextInputPanel.mm',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'

View File

@ -6,8 +6,6 @@
#ifndef mozView_h_
#define mozView_h_
#include "npapi.h"
#undef DARWIN
#import <Cocoa/Cocoa.h>
class nsIWidget;
@ -46,18 +44,12 @@ class TextInputHandler;
- (BOOL)isDragInProgress;
// Gets the plugin event model for the view
- (NPEventModel)pluginEventModel;
// Checks whether the view is first responder or not
- (BOOL)isFirstResponder;
// Call when you dispatch an event which may cause to open context menu.
- (void)maybeInitContextMenuTracking;
// Checks whether the view is for plugin or not
- (BOOL)isPluginView;
@end
// An informal protocol implemented by the NSWindow of the host application.

View File

@ -295,10 +295,6 @@ nsAppShell::Init()
rv = nsBaseAppShell::Init();
#ifndef __LP64__
TextInputHandler::InstallPluginKeyEventsHandler();
#endif
if (!gAppShellMethodsSwizzled) {
// We should only replace the original terminate: method if we're not
// running in a Cocoa embedder. See bug 604901.
@ -672,10 +668,6 @@ nsAppShell::Exit(void)
mTerminated = true;
#ifndef __LP64__
TextInputHandler::RemovePluginKeyEventsHandler();
#endif
// Quoting from Apple's doc on the [NSApplication stop:] method (from their
// doc on the NSApplication class): "If this method is invoked during a
// modal event loop, it will break that loop but not the main event loop."

View File

@ -16,8 +16,6 @@
#include "nsAutoPtr.h"
#include "nsISupports.h"
#include "nsBaseWidget.h"
#include "nsIPluginInstanceOwner.h"
#include "nsIPluginWidget.h"
#include "nsWeakPtr.h"
#include "TextInputHandler.h"
#include "nsCocoaUtils.h"
@ -31,62 +29,13 @@
#include "nsString.h"
#include "nsIDragService.h"
#include "npapi.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <AppKit/NSOpenGL.h>
// The header files QuickdrawAPI.h and QDOffscreen.h are missing on OS X 10.7
// and up (though the QuickDraw APIs defined in them are still present) -- so
// we need to supply the relevant parts of their contents here. It's likely
// that Apple will eventually remove the APIs themselves (probably in OS X
// 10.8), so we need to make them weak imports, and test for their presence
// before using them.
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(__QUICKDRAWAPI__)
extern void SetPort(GrafPtr port)
__attribute__((weak_import));
extern void SetOrigin(short h, short v)
__attribute__((weak_import));
extern RgnHandle NewRgn(void)
__attribute__((weak_import));
extern void DisposeRgn(RgnHandle rgn)
__attribute__((weak_import));
extern void RectRgn(RgnHandle rgn, const Rect * r)
__attribute__((weak_import));
extern GDHandle GetMainDevice(void)
__attribute__((weak_import));
extern Boolean IsPortOffscreen(CGrafPtr port)
__attribute__((weak_import));
extern void SetPortVisibleRegion(CGrafPtr port, RgnHandle visRgn)
__attribute__((weak_import));
extern void SetPortClipRegion(CGrafPtr port, RgnHandle clipRgn)
__attribute__((weak_import));
extern CGrafPtr GetQDGlobalsThePort(void)
__attribute__((weak_import));
#endif /* __QUICKDRAWAPI__ */
#if !defined(__QDOFFSCREEN__)
extern void GetGWorld(CGrafPtr * port, GDHandle * gdh)
__attribute__((weak_import));
extern void SetGWorld(CGrafPtr port, GDHandle gdh)
__attribute__((weak_import));
#endif /* __QDOFFSCREEN__ */
#ifdef __cplusplus
}
#endif
class gfxASurface;
class nsChildView;
class nsCocoaWindow;
union nsPluginPort;
namespace {
class GLPresenter;
@ -231,10 +180,6 @@ typedef NSInteger NSEventGestureAxis;
// cleared by [mozView uninstallTextInputHandler].
mozilla::widget::TextInputHandler* mTextInputHandler; // [WEAK]
BOOL mIsPluginView;
NPEventModel mPluginEventModel;
NPDrawingModel mPluginDrawingModel;
// when mouseDown: is called, we store its event here (strong)
NSEvent* mLastMouseDownEvent;
@ -326,12 +271,6 @@ typedef NSInteger NSEventGestureAxis;
- (void)updateGLContext;
- (void)_surfaceNeedsUpdate:(NSNotification*)notification;
- (BOOL)isPluginView;
// Are we processing an NSLeftMouseDown event that will fail to click through?
// If so, we shouldn't focus or unfocus a plugin.
- (BOOL)isInFailingLeftClickThrough;
- (void)setGLContext:(NSOpenGLContext *)aGLContext;
- (bool)preRender:(NSOpenGLContext *)aGLContext;
- (void)postRender:(NSOpenGLContext *)aGLContext;
@ -390,11 +329,6 @@ public:
static void ReEvaluateMouseEnterState(NSEvent* aEvent = nil, ChildView* aOldView = nil);
static void ResendLastMouseMoveEvent();
static ChildView* ViewForEvent(NSEvent* aEvent);
static void AttachPluginEvent(mozilla::WidgetMouseEventBase& aMouseEvent,
ChildView* aView,
NSEvent* aNativeMouseEvent,
int aPluginEventType,
void* aPluginEventHolder);
static ChildView* sLastMouseEventView;
static NSEvent* sLastMouseMoveEvent;
@ -408,8 +342,7 @@ public:
//
//-------------------------------------------------------------------------
class nsChildView : public nsBaseWidget,
public nsIPluginWidget
class nsChildView : public nsBaseWidget
{
private:
typedef nsBaseWidget Inherited;
@ -418,8 +351,6 @@ private:
public:
nsChildView();
NS_DECL_ISUPPORTS_INHERITED
// nsIWidget interface
NS_IMETHOD Create(nsIWidget *aParent,
nsNativeWidget aNativeParent,
@ -515,19 +446,6 @@ public:
NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode,
bool* aLEDState);
// nsIPluginWidget
// outClipRect and outOrigin are in display pixels (not device pixels)
NS_IMETHOD GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, bool& outWidgetVisible);
NS_IMETHOD StartDrawPlugin();
NS_IMETHOD EndDrawPlugin();
NS_IMETHOD SetPluginInstanceOwner(nsIPluginInstanceOwner* aInstanceOwner);
NS_IMETHOD SetPluginEventModel(int inEventModel);
NS_IMETHOD GetPluginEventModel(int* outEventModel);
NS_IMETHOD SetPluginDrawingModel(int inDrawingModel);
NS_IMETHOD StartComplexTextInputForCurrentEvent();
virtual nsTransparencyMode GetTransparencyMode();
virtual void SetTransparencyMode(nsTransparencyMode aMode);
@ -568,9 +486,6 @@ public:
virtual void UpdateWindowDraggingRegion(const nsIntRegion& aRegion) MOZ_OVERRIDE;
const nsIntRegion& GetDraggableRegion() { return mDraggableRegion; }
void HidePlugin();
void UpdatePluginPort();
void ResetParent();
static bool DoHasPendingInputEvent();
@ -579,8 +494,6 @@ public:
NSView<mozView>* GetEditorView();
bool IsPluginView() { return (mWindowType == eWindowType_plugin); }
nsCocoaWindow* GetXULWindowWidget();
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
@ -710,12 +623,8 @@ protected:
bool mVisible;
bool mDrawing;
bool mPluginDrawing;
bool mIsDispatchPaint; // Is a paint event being dispatched
NP_CGContext mPluginCGContext;
nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
// Used in OMTC BasicLayers mode. Presents the BasicCompositor result
// surface to the screen using an OpenGL context.
nsAutoPtr<GLPresenter> mGLPresenter;
@ -729,7 +638,4 @@ protected:
void ReleaseTitlebarCGContext();
};
void NS_InstallPluginKeyEventsHandler();
void NS_RemovePluginKeyEventsHandler();
#endif // nsChildView_h_

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,6 @@ public:
static bool OnMountainLionOrLater();
static bool OnMavericksOrLater();
static bool OnYosemiteOrLater();
static bool SupportCoreAnimationPlugins();
static bool AccelerateByDefault();
static bool IsAtLeastVersion(int32_t aMajor, int32_t aMinor, int32_t aBugFix=0);

View File

@ -148,14 +148,6 @@ nsCocoaFeatures::OSXVersionBugFix()
return ExtractBugFixVersion(OSXVersion());
}
/* static */ bool
nsCocoaFeatures::SupportCoreAnimationPlugins()
{
// Disallow Core Animation on 10.5 because of crashes.
// See Bug 711564.
return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX);
}
/* static */ bool
nsCocoaFeatures::OnLionOrLater()
{

View File

@ -320,11 +320,6 @@ public:
*/
static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent);
/**
* Initializes aPluginEvent for aCocoaEvent.
*/
static void InitPluginEvent(mozilla::WidgetPluginEvent &aPluginEvent,
NPCocoaEvent &aCocoaEvent);
/**
* Initializes WidgetInputEvent for aNativeEvent or aModifiers.
*/

View File

@ -606,16 +606,6 @@ nsCocoaUtils::InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent)
memset(aNPCocoaEvent, 0, sizeof(NPCocoaEvent));
}
// static
void
nsCocoaUtils::InitPluginEvent(WidgetPluginEvent &aPluginEvent,
NPCocoaEvent &aCocoaEvent)
{
aPluginEvent.time = PR_IntervalNow();
aPluginEvent.mPluginEvent.Copy(aCocoaEvent);
aPluginEvent.retargetToFocusedDocument = false;
}
// static
void
nsCocoaUtils::InitInputEvent(WidgetInputEvent& aInputEvent,

View File

@ -141,12 +141,12 @@ nsCocoaWindow::~nsCocoaWindow()
// Notify the children that we're gone. Popup windows (e.g. tooltips) can
// have nsChildView children. 'kid' is an nsChildView object if and only if
// its 'type' is 'eWindowType_child' or 'eWindowType_plugin'.
// its 'type' is 'eWindowType_child'.
// childView->ResetParent() can change our list of children while it's
// being iterated, so the way we iterate the list must allow for this.
for (nsIWidget* kid = mLastChild; kid;) {
nsWindowType kidType = kid->WindowType();
if (kidType == eWindowType_child || kidType == eWindowType_plugin) {
if (kidType == eWindowType_child) {
nsChildView* childView = static_cast<nsChildView*>(kid);
kid = kid->GetPrevSibling();
childView->ResetParent();
@ -2503,8 +2503,9 @@ nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
{
if (!mToplevelActiveState && mGeckoWindow) {
nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
if (listener)
if (listener) {
listener->WindowActivated();
}
mToplevelActiveState = true;
}
}
@ -2513,8 +2514,9 @@ nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
{
if (mToplevelActiveState && mGeckoWindow) {
nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
if (listener)
if (listener) {
listener->WindowDeactivated();
}
mToplevelActiveState = false;
}
}

View File

@ -832,41 +832,18 @@ static BOOL gMenuItemsExecuteCommands = YES;
return [super performKeyEquivalent:theEvent];
}
// Plugins normally eat all keyboard commands, this hack mitigates
// the problem.
BOOL handleForPluginHack = NO;
NSResponder *firstResponder = [keyWindow firstResponder];
if (firstResponder &&
[firstResponder isKindOfClass:[ChildView class]] &&
[(ChildView*)firstResponder isPluginView]) {
handleForPluginHack = YES;
// Maintain a list of cmd+key combinations that we never act on (in the
// browser) when the keyboard focus is in a plugin. What a particular
// cmd+key combo means here (to the browser) is governed by browser.dtd,
// which "contains the browser main menu items".
UInt32 modifierFlags = [theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask;
if (modifierFlags == NSCommandKeyMask) {
NSString *unmodchars = [theEvent charactersIgnoringModifiers];
if ([unmodchars length] == 1) {
if ([unmodchars characterAtIndex:0] == nsMenuBarX::GetLocalizedAccelKey("key_selectAll")) {
handleForPluginHack = NO;
}
}
}
}
gMenuItemsExecuteCommands = handleForPluginHack;
gMenuItemsExecuteCommands = NO;
[super performKeyEquivalent:theEvent];
gMenuItemsExecuteCommands = YES; // return to default
// Return YES if we invoked a command and there is now no key window or we changed
// the first responder. In this case we do not want to propagate the event because
// we don't want it handled again.
if (handleForPluginHack) {
if (![NSApp keyWindow] || [[NSApp keyWindow] firstResponder] != firstResponder) {
return YES;
}
}
// Return NO so that we can handle the event via NSView's "keyDown:".
return NO;

View File

@ -331,6 +331,12 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
WriteParam(aMsg, aParam.mIsRepeat);
WriteParam(aMsg, aParam.location);
WriteParam(aMsg, aParam.mUniqueId);
#ifdef XP_MACOSX
WriteParam(aMsg, aParam.mNativeKeyCode);
WriteParam(aMsg, aParam.mNativeModifierFlags);
WriteParam(aMsg, aParam.mNativeCharacters);
WriteParam(aMsg, aParam.mNativeCharactersIgnoringModifiers);
#endif
// An OS-specific native event might be attached in |mNativeKeyEvent|, but
// that cannot be copied across process boundaries.
}
@ -350,7 +356,14 @@ struct ParamTraits<mozilla::WidgetKeyboardEvent>
ReadParam(aMsg, aIter, &aResult->isChar) &&
ReadParam(aMsg, aIter, &aResult->mIsRepeat) &&
ReadParam(aMsg, aIter, &aResult->location) &&
ReadParam(aMsg, aIter, &aResult->mUniqueId))
ReadParam(aMsg, aIter, &aResult->mUniqueId)
#ifdef XP_MACOSX
&& ReadParam(aMsg, aIter, &aResult->mNativeKeyCode)
&& ReadParam(aMsg, aIter, &aResult->mNativeModifierFlags)
&& ReadParam(aMsg, aIter, &aResult->mNativeCharacters)
&& ReadParam(aMsg, aIter, &aResult->mNativeCharactersIgnoringModifiers)
#endif
)
{
aResult->mKeyNameIndex = static_cast<mozilla::KeyNameIndex>(keyNameIndex);
aResult->mCodeNameIndex =