diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index 14873d855b7..ef7204a76af 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -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; } diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 4d9b5ad1c7a..58864bd33a9 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -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); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 8bee1836ccf..54f7fc08263 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -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); diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 957b0d4aeda..399ec4e5b57 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -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 CreatePluginWidget(nsIWidget* aParent); + nsIntPoint GetChromeDisplacement() { return mChromeDisp; }; + protected: virtual ~TabChild(); @@ -653,6 +656,8 @@ private: nsRefPtr mActiveElementManager; bool mHasValidInnerSize; bool mDestroyed; + // Position of tab, relative to parent widget (typically the window) + nsIntPoint mChromeDisp; TabId mUniqueId; DISALLOW_EVIL_CONSTRUCTORS(TabChild); diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index f876ec22209..8bbf8730cf4 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -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); } } diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 084fb671ed2..44c02175f3f 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -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); diff --git a/dom/plugins/base/moz.build b/dom/plugins/base/moz.build index 262ad152e10..4dabdef3832 100644 --- a/dom/plugins/base/moz.build +++ b/dom/plugins/base/moz.build @@ -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', ] diff --git a/dom/plugins/base/nsNPAPIPlugin.cpp b/dom/plugins/base/nsNPAPIPlugin.cpp index a4b3ab703fb..c3f95e48137 100644 --- a/dom/plugins/base/nsNPAPIPlugin.cpp +++ b/dom/plugins/base/nsNPAPIPlugin.cpp @@ -52,6 +52,7 @@ #include #include #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(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 diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index c42f47e09b1..5d809fea64e 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -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; } diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index 544ff9aee9d..1c9f8ae016d 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -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 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! diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 46a2c5cb23a..794fb6076e4 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -57,6 +57,8 @@ using mozilla::DefaultXDisplay; #include "mozilla/dom/HTMLObjectElementBinding.h" #include "mozilla/dom/TabChild.h" #include "nsFrameSelection.h" +#include "PuppetWidget.h" +#include "nsPIWindowRoot.h" #include "nsContentCID.h" #include "nsWidgetsCID.h" @@ -69,8 +71,9 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); #endif #ifdef XP_MACOSX -#include -#include "nsPluginUtilsOSX.h" +#include "ComplexTextInputPanel.h" +#include "nsIDOMXULDocument.h" +#include "nsIDOMXULCommandDispatcher.h" #endif #ifdef MOZ_WIDGET_GTK @@ -95,6 +98,10 @@ using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::layers; +static inline nsPoint AsNsPoint(const nsIntPoint &p) { + return nsPoint(p.x, p.y); +} + // special class for handeling DOM context menu events because for // some reason it starves other mouse events if implemented on the // same class @@ -330,8 +337,11 @@ nsPluginInstanceOwner::nsPluginInstanceOwner() memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext)); mInCGPaintLevel = 0; mSentInitialTopLevelWindowEvent = false; + mLastWindowIsActive = false; + mLastContentFocused = false; + mLastScaleFactor = 1.0; mColorProfile = nullptr; - mPluginPortChanged = false; + mShouldBlurOnActivate = false; #endif mContentFocused = false; mWidgetVisible = true; @@ -729,33 +739,252 @@ NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel) #endif } +// This is no longer used, just leaving it here so we don't have to change +// the nsIPluginInstanceOwner interface. NPError nsPluginInstanceOwner::ShowNativeContextMenu(NPMenu* menu, void* event) { - if (!menu || !event) - return NPERR_GENERIC_ERROR; + return NPERR_GENERIC_ERROR; +} #ifdef XP_MACOSX - if (GetEventModel() != NPEventModelCocoa) - return NPERR_INCOMPATIBLE_VERSION_ERROR; +NPBool nsPluginInstanceOwner::ConvertPointPuppet(PuppetWidget *widget, + nsPluginFrame* pluginFrame, + double sourceX, double sourceY, + NPCoordinateSpace sourceSpace, + double *destX, double *destY, + NPCoordinateSpace destSpace) +{ + NS_ENSURE_TRUE(widget && widget->GetOwningTabChild() && pluginFrame, false); + // Caller has to want a result. + NS_ENSURE_TRUE(destX || destY, false); - return NS_NPAPI_ShowCocoaContextMenu(static_cast(menu), mWidget, - static_cast(event)); -#else - return NPERR_INCOMPATIBLE_VERSION_ERROR; -#endif + if (sourceSpace == destSpace) { + if (destX) { + *destX = sourceX; + } + if (destY) { + *destY = sourceY; + } + return true; + } + + nsPresContext* presContext = pluginFrame->PresContext(); + double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/ + presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); + + PuppetWidget *puppetWidget = static_cast(widget); + PuppetWidget *rootWidget = static_cast(widget->GetTopLevelWidget()); + if (!rootWidget) { + return false; + } + nsPoint chromeSize = AsNsPoint(rootWidget->GetChromeDimensions()) / scaleFactor; + nsIntSize intScreenDims = rootWidget->GetScreenDimensions(); + nsSize screenDims = nsSize(intScreenDims.width / scaleFactor, + intScreenDims.height / scaleFactor); + int32_t screenH = screenDims.height; + nsPoint windowPosition = AsNsPoint(rootWidget->GetWindowPosition()) / scaleFactor; + + // Window size is tab size + chrome size. + nsIntRect tabContentBounds; + NS_ENSURE_SUCCESS(puppetWidget->GetBounds(tabContentBounds), false); + tabContentBounds.ScaleInverseRoundOut(scaleFactor); + int32_t windowH = tabContentBounds.height + int(chromeSize.y); + + // This is actually relative to window-chrome. + nsPoint pluginPosition = AsNsPoint(pluginFrame->GetScreenRect().TopLeft()); + + // Convert (sourceX, sourceY) to 'real' (not PuppetWidget) screen space. + // In OSX, the Y-axis increases upward, which is the reverse of ours. + // We want OSX coordinates for window and screen so those equations are swapped. + nsPoint sourcePoint(sourceX, sourceY); + nsPoint screenPoint; + switch (sourceSpace) { + case NPCoordinateSpacePlugin: + screenPoint = sourcePoint + pluginFrame->GetContentRectRelativeToSelf().TopLeft() + + chromeSize + pluginPosition + windowPosition; + break; + case NPCoordinateSpaceWindow: + screenPoint = nsPoint(sourcePoint.x, windowH-sourcePoint.y) + + windowPosition; + break; + case NPCoordinateSpaceFlippedWindow: + screenPoint = sourcePoint + windowPosition; + break; + case NPCoordinateSpaceScreen: + screenPoint = nsPoint(sourcePoint.x, screenH-sourcePoint.y); + break; + case NPCoordinateSpaceFlippedScreen: + screenPoint = sourcePoint; + break; + default: + return false; + } + + // Convert from screen to dest space. + nsPoint destPoint; + switch (destSpace) { + case NPCoordinateSpacePlugin: + destPoint = screenPoint - pluginFrame->GetContentRectRelativeToSelf().TopLeft() - + chromeSize - pluginPosition - windowPosition; + break; + case NPCoordinateSpaceWindow: + destPoint = screenPoint - windowPosition; + destPoint.y = windowH - destPoint.y; + break; + case NPCoordinateSpaceFlippedWindow: + destPoint = screenPoint - windowPosition; + break; + case NPCoordinateSpaceScreen: + destPoint = nsPoint(screenPoint.x, screenH-screenPoint.y); + break; + case NPCoordinateSpaceFlippedScreen: + destPoint = screenPoint; + break; + default: + return false; + } + + if (destX) { + *destX = destPoint.x; + } + if (destY) { + *destY = destPoint.y; + } + + return true; } +NPBool nsPluginInstanceOwner::ConvertPointNoPuppet(nsIWidget *widget, + nsPluginFrame* pluginFrame, + double sourceX, double sourceY, + NPCoordinateSpace sourceSpace, + double *destX, double *destY, + NPCoordinateSpace destSpace) +{ + NS_ENSURE_TRUE(widget && pluginFrame, false); + // Caller has to want a result. + NS_ENSURE_TRUE(destX || destY, false); + + if (sourceSpace == destSpace) { + if (destX) { + *destX = sourceX; + } + if (destY) { + *destY = sourceY; + } + return true; + } + + nsPresContext* presContext = pluginFrame->PresContext(); + double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/ + presContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); + + nsCOMPtr screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1"); + if (!screenMgr) { + return false; + } + nsCOMPtr screen; + screenMgr->ScreenForNativeWidget(widget->GetNativeData(NS_NATIVE_WINDOW), getter_AddRefs(screen)); + if (!screen) { + return false; + } + + int32_t screenX, screenY, screenWidth, screenHeight; + screen->GetRect(&screenX, &screenY, &screenWidth, &screenHeight); + screenHeight /= scaleFactor; + + nsIntRect windowScreenBounds; + NS_ENSURE_SUCCESS(widget->GetScreenBounds(windowScreenBounds), false); + windowScreenBounds.ScaleInverseRoundOut(scaleFactor); + int32_t windowX = windowScreenBounds.x; + int32_t windowY = windowScreenBounds.y; + int32_t windowHeight = windowScreenBounds.height; + + nsIntRect pluginScreenRect = pluginFrame->GetScreenRect(); + + double screenXGecko, screenYGecko; + switch (sourceSpace) { + case NPCoordinateSpacePlugin: + screenXGecko = pluginScreenRect.x + sourceX; + screenYGecko = pluginScreenRect.y + sourceY; + break; + case NPCoordinateSpaceWindow: + screenXGecko = windowX + sourceX; + screenYGecko = windowY + (windowHeight - sourceY); + break; + case NPCoordinateSpaceFlippedWindow: + screenXGecko = windowX + sourceX; + screenYGecko = windowY + sourceY; + break; + case NPCoordinateSpaceScreen: + screenXGecko = sourceX; + screenYGecko = screenHeight - sourceY; + break; + case NPCoordinateSpaceFlippedScreen: + screenXGecko = sourceX; + screenYGecko = sourceY; + break; + default: + return false; + } + + double destXCocoa, destYCocoa; + switch (destSpace) { + case NPCoordinateSpacePlugin: + destXCocoa = screenXGecko - pluginScreenRect.x; + destYCocoa = screenYGecko - pluginScreenRect.y; + break; + case NPCoordinateSpaceWindow: + destXCocoa = screenXGecko - windowX; + destYCocoa = windowHeight - (screenYGecko - windowY); + break; + case NPCoordinateSpaceFlippedWindow: + destXCocoa = screenXGecko - windowX; + destYCocoa = screenYGecko - windowY; + break; + case NPCoordinateSpaceScreen: + destXCocoa = screenXGecko; + destYCocoa = screenHeight - screenYGecko; + break; + case NPCoordinateSpaceFlippedScreen: + destXCocoa = screenXGecko; + destYCocoa = screenYGecko; + break; + default: + return false; + } + + if (destX) { + *destX = destXCocoa; + } + if (destY) { + *destY = destYCocoa; + } + + return true; +} +#endif // XP_MACOSX + NPBool nsPluginInstanceOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace) { #ifdef XP_MACOSX - if (!mWidget) + if (!mPluginFrame) { return false; + } - return NS_NPAPI_ConvertPointCocoa(mWidget->GetNativeData(NS_NATIVE_WIDGET), - sourceX, sourceY, sourceSpace, destX, destY, destSpace); + MOZ_ASSERT(mPluginFrame->GetNearestWidget()); + + if (nsIWidget::UsePuppetWidgets()) { + return ConvertPointPuppet(static_cast(mPluginFrame->GetNearestWidget()), + mPluginFrame, sourceX, sourceY, sourceSpace, + destX, destY, destSpace); + } + + return ConvertPointNoPuppet(mPluginFrame->GetNearestWidget(), + mPluginFrame, sourceX, sourceY, sourceSpace, + destX, destY, destSpace); #else - // we should implement this for all platforms return false; #endif } @@ -1004,28 +1233,12 @@ void* nsPluginInstanceOwner::GetPluginPortCopy() return nullptr; } -// Currently (on OS X in Cocoa widgets) any changes made as a result of -// calling GetPluginPortFromWidget() are immediately reflected in the NPWindow -// structure that has been passed to the plugin via SetWindow(). This is -// because calls to nsChildView::GetNativeData(NS_NATIVE_PLUGIN_PORT_CG) -// always return a pointer to the same internal (private) object, but may -// make changes inside that object. All calls to GetPluginPortFromWidget() made while -// the plugin is active (i.e. excluding those made at our initialization) -// need to take this into account. The easiest way to do so is to replace -// them with calls to SetPluginPortAndDetectChange(). This method keeps track -// of when calls to GetPluginPortFromWidget() result in changes, and sets a flag to make -// sure SetWindow() gets called the next time through FixUpPluginWindow(), so -// that the plugin is notified of these changes. -void* nsPluginInstanceOwner::SetPluginPortAndDetectChange() +void nsPluginInstanceOwner::SetPluginPort() { - if (!mPluginWindow) - return nullptr; - void* pluginPort = GetPluginPortFromWidget(); - if (!pluginPort) - return nullptr; + void* pluginPort = GetPluginPort(); + if (!pluginPort || !mPluginWindow) + return; mPluginWindow->window = pluginPort; - - return mPluginWindow->window; } void nsPluginInstanceOwner::BeginCGPaint() @@ -1271,7 +1484,6 @@ nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent) WidgetEvent* theEvent = aFocusEvent->GetInternalNSEvent(); if (theEvent) { - // we only care about the message in ProcessEvent WidgetGUIEvent focusEvent(theEvent->mFlags.mIsTrusted, theEvent->message, nullptr); nsEventStatus rv = ProcessEvent(focusEvent); @@ -1395,6 +1607,23 @@ nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent) nsAutoString eventType; aEvent->GetType(eventType); + +#ifdef XP_MACOSX + if (eventType.EqualsLiteral("activate") || + eventType.EqualsLiteral("deactivate")) { + WindowFocusMayHaveChanged(); + return NS_OK; + } + if (eventType.EqualsLiteral("MozPerformDelayedBlur")) { + if (mShouldBlurOnActivate) { + WidgetGUIEvent blurEvent(true, NS_BLUR_CONTENT, nullptr); + ProcessEvent(blurEvent); + mShouldBlurOnActivate = false; + } + return NS_OK; + } +#endif + if (eventType.EqualsLiteral("focus")) { mContentFocused = true; return DispatchFocusToPlugin(aEvent); @@ -1407,18 +1636,6 @@ nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent) return ProcessMouseDown(aEvent); } if (eventType.EqualsLiteral("mouseup")) { - // Don't send a mouse-up event to the plugin if its button type doesn't - // match that of the preceding mouse-down event (if any). This kind of - // mismatch can happen if the previous mouse-down event was sent to a DOM - // element above the plugin, the mouse is still above the plugin, and the - // mouse-down event caused the element to disappear. See bug 627649 and - // bug 909678. - WidgetMouseEvent* mouseEvent = aEvent->GetInternalNSEvent()->AsMouseEvent(); - if (mouseEvent && - static_cast(mouseEvent->button) != mLastMouseDownButtonType) { - aEvent->PreventDefault(); - return NS_OK; - } return DispatchMouseToPlugin(aEvent); } if (eventType.EqualsLiteral("mousemove")) { @@ -1464,113 +1681,286 @@ static unsigned int XInputEventState(const WidgetInputEvent& anEvent) } #endif +#ifdef XP_MACOSX + +// Returns whether or not content is the content that is or would be +// focused if the top-level chrome window was active. +static bool +ContentIsFocusedWithinWindow(nsIContent* aContent) +{ + nsPIDOMWindow* outerWindow = aContent->OwnerDoc()->GetWindow(); + if (!outerWindow) { + return false; + } + + nsPIDOMWindow* rootWindow = outerWindow->GetPrivateRoot(); + if (!rootWindow) { + return false; + } + + nsFocusManager* fm = nsFocusManager::GetFocusManager(); + if (!fm) { + return false; + } + + nsCOMPtr focusedFrame; + nsCOMPtr focusedContent = fm->GetFocusedDescendant(rootWindow, true, getter_AddRefs(focusedFrame)); + return (focusedContent.get() == aContent); +} + +static NPCocoaEventType +CocoaEventTypeForEvent(const WidgetGUIEvent& anEvent, nsIFrame* aObjectFrame) +{ + const NPCocoaEvent* event = static_cast(anEvent.mPluginEvent); + if (event) { + return event->type; + } + + switch (anEvent.message) { + case NS_MOUSE_ENTER_SYNTH: + return NPCocoaEventMouseEntered; + case NS_MOUSE_EXIT_SYNTH: + return NPCocoaEventMouseExited; + case NS_MOUSE_MOVE: + { + // We don't know via information on events from the widget code whether or not + // we're dragging. The widget code just generates mouse move events from native + // drag events. If anybody is capturing, this is a drag event. + if (nsIPresShell::GetCapturingContent()) { + return NPCocoaEventMouseDragged; + } + + return NPCocoaEventMouseMoved; + } + case NS_MOUSE_BUTTON_DOWN: + return NPCocoaEventMouseDown; + case NS_MOUSE_BUTTON_UP: + return NPCocoaEventMouseUp; + case NS_KEY_DOWN: + return NPCocoaEventKeyDown; + case NS_KEY_UP: + return NPCocoaEventKeyUp; + case NS_FOCUS_CONTENT: + case NS_BLUR_CONTENT: + return NPCocoaEventFocusChanged; + case NS_MOUSE_SCROLL: + return NPCocoaEventScrollWheel; + default: + return (NPCocoaEventType)0; + } +} + +static NPCocoaEvent +TranslateToNPCocoaEvent(WidgetGUIEvent* anEvent, nsIFrame* aObjectFrame) +{ + NPCocoaEvent cocoaEvent; + InitializeNPCocoaEvent(&cocoaEvent); + cocoaEvent.type = CocoaEventTypeForEvent(*anEvent, aObjectFrame); + + if (anEvent->message == NS_MOUSE_MOVE || + anEvent->message == NS_MOUSE_BUTTON_DOWN || + anEvent->message == NS_MOUSE_BUTTON_UP || + anEvent->message == NS_MOUSE_SCROLL || + anEvent->message == NS_MOUSE_ENTER_SYNTH || + anEvent->message == NS_MOUSE_EXIT_SYNTH) + { + nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(anEvent, aObjectFrame) - + aObjectFrame->GetContentRectRelativeToSelf().TopLeft(); + nsPresContext* presContext = aObjectFrame->PresContext(); + // Plugin event coordinates need to be translated from device pixels + // into "display pixels" in HiDPI modes. + double scaleFactor = double(nsPresContext::AppUnitsPerCSSPixel())/ + aObjectFrame->PresContext()->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom(); + size_t intScaleFactor = ceil(scaleFactor); + nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor, + presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor); + cocoaEvent.data.mouse.pluginX = double(ptPx.x); + cocoaEvent.data.mouse.pluginY = double(ptPx.y); + } + + switch (anEvent->message) { + case NS_MOUSE_BUTTON_DOWN: + case NS_MOUSE_BUTTON_UP: + { + WidgetMouseEvent* mouseEvent = anEvent->AsMouseEvent(); + if (mouseEvent) { + switch (mouseEvent->button) { + case WidgetMouseEvent::eLeftButton: + cocoaEvent.data.mouse.buttonNumber = 0; + break; + case WidgetMouseEvent::eRightButton: + cocoaEvent.data.mouse.buttonNumber = 1; + break; + case WidgetMouseEvent::eMiddleButton: + cocoaEvent.data.mouse.buttonNumber = 2; + break; + default: + NS_WARNING("Mouse button we don't know about?"); + } + cocoaEvent.data.mouse.clickCount = mouseEvent->clickCount; + } else { + NS_WARNING("NS_MOUSE_BUTTON_UP/DOWN is not a WidgetMouseEvent?"); + } + break; + } + case NS_MOUSE_SCROLL: + { + WidgetWheelEvent* wheelEvent = anEvent->AsWheelEvent(); + if (wheelEvent) { + cocoaEvent.data.mouse.deltaX = wheelEvent->lineOrPageDeltaX; + cocoaEvent.data.mouse.deltaY = wheelEvent->lineOrPageDeltaY; + } else { + NS_WARNING("NS_MOUSE_SCROLL is not a WidgetWheelEvent? (could be, haven't checked)"); + } + break; + } + case NS_KEY_DOWN: + case NS_KEY_UP: + { + WidgetKeyboardEvent* keyEvent = anEvent->AsKeyboardEvent(); + + cocoaEvent.data.key.keyCode = keyEvent->mNativeKeyCode; + cocoaEvent.data.key.isARepeat = keyEvent->mIsRepeat; + cocoaEvent.data.key.modifierFlags = keyEvent->mNativeModifierFlags; + const char16_t* nativeChars = keyEvent->mNativeCharacters.get(); + cocoaEvent.data.key.characters = + (NPNSString*)::CFStringCreateWithCharacters(NULL, + reinterpret_cast(nativeChars), + keyEvent->mNativeCharacters.Length()); + const char16_t* nativeCharsIgnoringModifiers = keyEvent->mNativeCharactersIgnoringModifiers.get(); + cocoaEvent.data.key.charactersIgnoringModifiers = + (NPNSString*)::CFStringCreateWithCharacters(NULL, + reinterpret_cast(nativeCharsIgnoringModifiers), + keyEvent->mNativeCharactersIgnoringModifiers.Length()); + break; + } + case NS_FOCUS_CONTENT: + case NS_BLUR_CONTENT: + cocoaEvent.data.focus.hasFocus = (anEvent->message == NS_FOCUS_CONTENT); + break; + default: + break; + } + return cocoaEvent; +} + +void nsPluginInstanceOwner::PerformDelayedBlurs() +{ + nsCOMPtr windowRoot = mContent->OwnerDoc()->GetWindow()->GetTopWindowRoot(); + nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(), + windowRoot, + NS_LITERAL_STRING("MozPerformDelayedBlur"), + false, false, nullptr); +} + +#endif + nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent) { nsEventStatus rv = nsEventStatus_eIgnore; - if (!mInstance || !mPluginFrame) // if mInstance is null, we shouldn't be here + if (!mInstance || !mPluginFrame) { return nsEventStatus_eIgnore; + } #ifdef XP_MACOSX - if (!mWidget) - return nsEventStatus_eIgnore; - - // we never care about synthesized mouse enter - if (anEvent.message == NS_MOUSE_ENTER_SYNTH) - return nsEventStatus_eIgnore; - - nsCOMPtr pluginWidget = do_QueryInterface(mWidget); - if (!pluginWidget || NS_FAILED(pluginWidget->StartDrawPlugin())) - return nsEventStatus_eIgnore; - NPEventModel eventModel = GetEventModel(); + if (eventModel != NPEventModelCocoa) { + return nsEventStatus_eIgnore; + } - // If we have to synthesize an event we'll use one of these. - NPCocoaEvent synthCocoaEvent; - const NPCocoaEvent* event = static_cast(anEvent.mPluginEvent); - nsPoint pt = - nsLayoutUtils::GetEventCoordinatesRelativeTo(&anEvent, mPluginFrame) - - mPluginFrame->GetContentRectRelativeToSelf().TopLeft(); - nsPresContext* presContext = mPluginFrame->PresContext(); - // Plugin event coordinates need to be translated from device pixels - // into "display pixels" in HiDPI modes. - double scaleFactor = 1.0; - GetContentsScaleFactor(&scaleFactor); - size_t intScaleFactor = ceil(scaleFactor); - nsIntPoint ptPx(presContext->AppUnitsToDevPixels(pt.x) / intScaleFactor, - presContext->AppUnitsToDevPixels(pt.y) / intScaleFactor); + // In the Cocoa event model, focus is per-window. Don't tell a plugin it lost + // focus unless it lost focus within the window. For example, ignore a blur + // event if it's coming due to the plugin's window deactivating. + if (anEvent.message == NS_BLUR_CONTENT && + ContentIsFocusedWithinWindow(mContent)) { + mShouldBlurOnActivate = true; + return nsEventStatus_eIgnore; + } - if (!event) { - InitializeNPCocoaEvent(&synthCocoaEvent); - switch (anEvent.message) { - case NS_MOUSE_MOVE: - { - // Ignore mouse-moved events that happen as part of a dragging - // operation that started over another frame. See bug 525078. - nsRefPtr frameselection = mPluginFrame->GetFrameSelection(); - if (!frameselection->GetDragState() || - (nsIPresShell::GetCapturingContent() == mPluginFrame->GetContent())) { - synthCocoaEvent.type = NPCocoaEventMouseMoved; - synthCocoaEvent.data.mouse.pluginX = static_cast(ptPx.x); - synthCocoaEvent.data.mouse.pluginY = static_cast(ptPx.y); - event = &synthCocoaEvent; - } + // Also, don't tell the plugin it gained focus again after we've already given + // it focus. This might happen if it has focus, its window is blurred, then the + // window is made active again. The plugin never lost in-window focus, so it + // shouldn't get a focus event again. + if (anEvent.message == NS_FOCUS_CONTENT && + mLastContentFocused == true) { + mShouldBlurOnActivate = false; + return nsEventStatus_eIgnore; + } + + // Now, if we're going to send a focus event, update mLastContentFocused and + // tell any plugins in our window that we have taken focus, so they should + // perform any delayed blurs. + if (anEvent.message == NS_FOCUS_CONTENT || + anEvent.message == NS_BLUR_CONTENT) { + mLastContentFocused = (anEvent.message == NS_FOCUS_CONTENT); + mShouldBlurOnActivate = false; + PerformDelayedBlurs(); + } + + NPCocoaEvent cocoaEvent = TranslateToNPCocoaEvent(const_cast(&anEvent), mPluginFrame); + if (cocoaEvent.type == (NPCocoaEventType)0) { + return nsEventStatus_eIgnore; + } + + if (cocoaEvent.type == NPCocoaEventKeyDown) { + ComplexTextInputPanel* ctiPanel = ComplexTextInputPanel::GetSharedComplexTextInputPanel(); + if (ctiPanel && ctiPanel->IsInComposition()) { + nsAutoString outText; + ctiPanel->InterpretKeyEvent(&cocoaEvent, outText); + if (!outText.IsEmpty()) { + CFStringRef cfString = ::CFStringCreateWithCharacters(kCFAllocatorDefault, + reinterpret_cast(outText.get()), + outText.Length()); + + NPCocoaEvent textEvent; + InitializeNPCocoaEvent(&textEvent); + textEvent.type = NPCocoaEventTextInput; + textEvent.data.text.text = (NPNSString*)cfString; + + mInstance->HandleEvent(&textEvent, nullptr); } - break; - case NS_MOUSE_BUTTON_DOWN: - synthCocoaEvent.type = NPCocoaEventMouseDown; - synthCocoaEvent.data.mouse.pluginX = static_cast(ptPx.x); - synthCocoaEvent.data.mouse.pluginY = static_cast(ptPx.y); - event = &synthCocoaEvent; - break; - case NS_MOUSE_BUTTON_UP: - // If we're in a dragging operation that started over another frame, - // convert it into a mouse-entered event (in the Cocoa Event Model). - // See bug 525078. - if (anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton && - (nsIPresShell::GetCapturingContent() != mPluginFrame->GetContent())) { - synthCocoaEvent.type = NPCocoaEventMouseEntered; - synthCocoaEvent.data.mouse.pluginX = static_cast(ptPx.x); - synthCocoaEvent.data.mouse.pluginY = static_cast(ptPx.y); - event = &synthCocoaEvent; - } else { - synthCocoaEvent.type = NPCocoaEventMouseUp; - synthCocoaEvent.data.mouse.pluginX = static_cast(ptPx.x); - synthCocoaEvent.data.mouse.pluginY = static_cast(ptPx.y); - event = &synthCocoaEvent; - } - break; - default: - break; - } - - // If we still don't have an event, bail. - if (!event) { - pluginWidget->EndDrawPlugin(); - return nsEventStatus_eIgnore; + return nsEventStatus_eConsumeNoDefault; } } int16_t response = kNPEventNotHandled; - void* window = FixUpPluginWindow(ePluginPaintEnable); - if (window || (eventModel == NPEventModelCocoa)) { - mInstance->HandleEvent(const_cast(event), - &response, - NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); + mInstance->HandleEvent(&cocoaEvent, + &response, + NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); + if (response == kNPEventStartIME) { + nsAutoString outText; + ComplexTextInputPanel* ctiPanel = ComplexTextInputPanel::GetSharedComplexTextInputPanel(); + + // Place ctiPanel by passing the coordinates of the bottom-left of the plugin, + // in screen-coordinates. + double screenX, screenY; + ConvertPoint(0.0, mPluginFrame->GetScreenRect().height, NPCoordinateSpacePlugin, + &screenX, &screenY, NPCoordinateSpaceScreen); + + ctiPanel->PlacePanel(screenX, screenY); + ctiPanel->InterpretKeyEvent(&cocoaEvent, outText); + + if (!outText.IsEmpty()) { + CFStringRef cfString = ::CFStringCreateWithCharacters(kCFAllocatorDefault, + reinterpret_cast(outText.get()), + outText.Length()); + + NPCocoaEvent textEvent; + InitializeNPCocoaEvent(&textEvent); + textEvent.type = NPCocoaEventTextInput; + textEvent.data.text.text = (NPNSString*)cfString; + + mInstance->HandleEvent(&textEvent, nullptr); + } } - if (eventModel == NPEventModelCocoa && response == kNPEventStartIME) { - pluginWidget->StartComplexTextInputForCurrentEvent(); - } - - if ((response == kNPEventHandled || response == kNPEventStartIME) && - !(anEvent.message == NS_MOUSE_BUTTON_DOWN && - anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton && - !mContentFocused)) { + bool handled = (response == kNPEventHandled || response == kNPEventStartIME); + bool leftMouseButtonDown = (anEvent.message == NS_MOUSE_BUTTON_DOWN) && + (anEvent.AsMouseEvent()->button == WidgetMouseEvent::eLeftButton); + if (handled && !(leftMouseButtonDown && !mContentFocused)) { rv = nsEventStatus_eConsumeNoDefault; } - - pluginWidget->EndDrawPlugin(); #endif #ifdef XP_WIN @@ -2044,11 +2434,7 @@ void nsPluginInstanceOwner::Paint(const gfxRect& aDirtyRect, CGContextRef cgCont dirtyRectCopy.ScaleRoundOut(1.0 / scaleFactor); } - nsCOMPtr pluginWidget = do_QueryInterface(mWidget); - if (pluginWidget && NS_SUCCEEDED(pluginWidget->StartDrawPlugin())) { - DoCocoaEventDrawRect(dirtyRectCopy, cgContext); - pluginWidget->EndDrawPlugin(); - } + DoCocoaEventDrawRect(dirtyRectCopy, cgContext); } void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext) @@ -2409,7 +2795,7 @@ nsresult nsPluginInstanceOwner::Init(nsIContent* aContent) return NS_OK; } -void* nsPluginInstanceOwner::GetPluginPortFromWidget() +void* nsPluginInstanceOwner::GetPluginPort() { //!!! Port must be released for windowless plugins on Windows, because it is HDC !!! @@ -2419,16 +2805,10 @@ void* nsPluginInstanceOwner::GetPluginPortFromWidget() if (mPluginWindow && (mPluginWindow->type == NPWindowTypeDrawable)) result = mWidget->GetNativeData(NS_NATIVE_GRAPHIC); // HDC else -#endif -#ifdef XP_MACOSX - if (GetDrawingModel() == NPDrawingModelCoreGraphics || - GetDrawingModel() == NPDrawingModelCoreAnimation || - GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation) - result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT_CG); - else #endif result = mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT); // HWND/gdk window } + return result; } @@ -2503,21 +2883,6 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) mWidget->EnableDragDrop(true); mWidget->Show(false); mWidget->Enable(false); - -#ifdef XP_MACOSX - // Now that we have a widget we want to set the event model before - // any events are processed. - nsCOMPtr pluginWidget = do_QueryInterface(mWidget); - if (!pluginWidget) { - return NS_ERROR_FAILURE; - } - pluginWidget->SetPluginEventModel(GetEventModel()); - pluginWidget->SetPluginDrawingModel(GetDrawingModel()); - - if (GetDrawingModel() == NPDrawingModelCoreAnimation) { - AddToCARefreshTimer(); - } -#endif } if (mPluginFrame) { @@ -2548,7 +2913,7 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) // mPluginWindow->type is used in |GetPluginPort| so it must // be initialized first mPluginWindow->type = NPWindowTypeWindow; - mPluginWindow->window = GetPluginPortFromWidget(); + mPluginWindow->window = GetPluginPort(); // tell the plugin window about the widget mPluginWindow->SetPluginWidget(mWidget); @@ -2559,6 +2924,12 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) } } +#ifdef XP_MACOSX + if (GetDrawingModel() == NPDrawingModelCoreAnimation) { + AddToCARefreshTimer(); + } +#endif + mWidgetCreationComplete = true; return NS_OK; @@ -2567,71 +2938,30 @@ NS_IMETHODIMP nsPluginInstanceOwner::CreateWidget(void) // Mac specific code to fix up the port location and clipping region #ifdef XP_MACOSX -void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState) +void nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState) { - if (!mWidget || !mPluginWindow || !mInstance || !mPluginFrame) - return nullptr; - - nsCOMPtr pluginWidget = do_QueryInterface(mWidget); - if (!pluginWidget) - return nullptr; + if (!mPluginWindow || !mInstance || !mPluginFrame) { + return; + } // If we've already set up a CGContext in nsPluginFrame::PaintPlugin(), we - // don't want calls to SetPluginPortAndDetectChange() to step on our work. + // don't want calls to SetPluginPort() to step on our work. if (mInCGPaintLevel < 1) { - SetPluginPortAndDetectChange(); + SetPluginPort(); } - // We'll need the top-level Cocoa window for the Cocoa event model. - nsIWidget* widget = mPluginFrame->GetNearestWidget(); - if (!widget) - return nullptr; - void *cocoaTopLevelWindow = widget->GetNativeData(NS_NATIVE_WINDOW); - // We don't expect to have a top level window in a content process - if (!cocoaTopLevelWindow && XRE_GetProcessType() == GeckoProcessType_Default) { - return nullptr; - } + nsIntSize widgetClip = mPluginFrame->GetWidgetlessClipRect().Size(); - nsIntPoint pluginOrigin; - nsIntRect widgetClip; - bool widgetVisible; - pluginWidget->GetPluginClipRect(widgetClip, pluginOrigin, widgetVisible); - // TODO: Detect visibility for e10s mac plugins - if (XRE_GetProcessType() != GeckoProcessType_Default) { - widgetVisible = true; - } - mWidgetVisible = widgetVisible; - - // printf("GetPluginClipRect returning visible %d\n", widgetVisible); - - // This would be a lot easier if we could use obj-c here, - // but we can't. Since we have only nsIWidget and we can't - // use its native widget (an obj-c object) we have to go - // from the widget's screen coordinates to its window coords - // instead of straight to window coords. - nsIntPoint geckoScreenCoords = mWidget->WidgetToScreenOffset(); - - nsRect windowRect; - if (cocoaTopLevelWindow) { - NS_NPAPI_CocoaWindowFrame(cocoaTopLevelWindow, windowRect); - } - - double scaleFactor = 1.0; - GetContentsScaleFactor(&scaleFactor); - int intScaleFactor = ceil(scaleFactor); - - // Convert geckoScreenCoords from device pixels to "display pixels" - // for HiDPI modes. - mPluginWindow->x = geckoScreenCoords.x/intScaleFactor - windowRect.x; - mPluginWindow->y = geckoScreenCoords.y/intScaleFactor - windowRect.y; + mPluginWindow->x = 0; + mPluginWindow->y = 0; NPRect oldClipRect = mPluginWindow->clipRect; // fix up the clipping region - mPluginWindow->clipRect.top = widgetClip.y; - mPluginWindow->clipRect.left = widgetClip.x; + mPluginWindow->clipRect.top = 0; + mPluginWindow->clipRect.left = 0; - if (!mWidgetVisible || inPaintState == ePluginPaintDisable) { + if (inPaintState == ePluginPaintDisable) { mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top; mPluginWindow->clipRect.right = mPluginWindow->clipRect.left; } @@ -2655,8 +2985,7 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState) if (mPluginWindow->clipRect.left != oldClipRect.left || mPluginWindow->clipRect.top != oldClipRect.top || mPluginWindow->clipRect.right != oldClipRect.right || - mPluginWindow->clipRect.bottom != oldClipRect.bottom || - mPluginPortChanged) + mPluginWindow->clipRect.bottom != oldClipRect.bottom) { if (UseAsyncRendering()) { mInstance->AsyncSetWindow(mPluginWindow); @@ -2664,7 +2993,6 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState) else { mPluginWindow->CallSetWindow(mInstance); } - mPluginPortChanged = false; } // After the first NPP_SetWindow call we need to send an initial @@ -2673,16 +3001,62 @@ void* nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState) // Set this before calling ProcessEvent to avoid endless recursion. mSentInitialTopLevelWindowEvent = true; - WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, nullptr); - NPCocoaEvent cocoaEvent; - InitializeNPCocoaEvent(&cocoaEvent); - cocoaEvent.type = NPCocoaEventWindowFocusChanged; - cocoaEvent.data.focus.hasFocus = cocoaTopLevelWindow ? NS_NPAPI_CocoaWindowIsMain(cocoaTopLevelWindow) : true; - pluginEvent.mPluginEvent.Copy(cocoaEvent); - ProcessEvent(pluginEvent); + bool isActive = WindowIsActive(); + SendWindowFocusChanged(isActive); + mLastWindowIsActive = isActive; + } +} + +void +nsPluginInstanceOwner::WindowFocusMayHaveChanged() +{ + if (!mSentInitialTopLevelWindowEvent) { + return; } - return nullptr; + bool isActive = WindowIsActive(); + if (isActive != mLastWindowIsActive) { + SendWindowFocusChanged(isActive); + mLastWindowIsActive = isActive; + } +} + +bool +nsPluginInstanceOwner::WindowIsActive() +{ + if (!mPluginFrame) { + return false; + } + + EventStates docState = mPluginFrame->GetContent()->OwnerDoc()->GetDocumentState(); + return !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE); +} + +void +nsPluginInstanceOwner::SendWindowFocusChanged(bool aIsActive) +{ + if (!mInstance) { + return; + } + + NPCocoaEvent cocoaEvent; + InitializeNPCocoaEvent(&cocoaEvent); + cocoaEvent.type = NPCocoaEventWindowFocusChanged; + cocoaEvent.data.focus.hasFocus = aIsActive; + mInstance->HandleEvent(&cocoaEvent, + nullptr, + NS_PLUGIN_CALL_SAFE_TO_REENTER_GECKO); +} + +void +nsPluginInstanceOwner::ResolutionMayHaveChanged() +{ + double scaleFactor = 1.0; + GetContentsScaleFactor(&scaleFactor); + if (scaleFactor != mLastScaleFactor) { + ContentsScaleFactorChanged(scaleFactor); + mLastScaleFactor = scaleFactor; + } } void @@ -2836,6 +3210,18 @@ void nsPluginInstanceOwner::SetFrame(nsPluginFrame *aFrame) // If we already have a frame that is changing or going away... if (mPluginFrame) { + if (mContent && mContent->OwnerDoc() && mContent->OwnerDoc()->GetWindow()) { + nsCOMPtr windowRoot = mContent->OwnerDoc()->GetWindow()->GetTopWindowRoot(); + if (windowRoot) { + windowRoot->RemoveEventListener(NS_LITERAL_STRING("activate"), + this, false); + windowRoot->RemoveEventListener(NS_LITERAL_STRING("deactivate"), + this, false); + windowRoot->RemoveEventListener(NS_LITERAL_STRING("MozPerformDelayedBlur"), + this, false); + } + } + // Make sure the old frame isn't holding a reference to us. mPluginFrame->SetInstanceOwner(nullptr); } @@ -2859,6 +3245,19 @@ void nsPluginInstanceOwner::SetFrame(nsPluginFrame *aFrame) if (fm && content) { mContentFocused = (content == fm->GetFocusedContent()); } + + // Register for widget-focus events on the window root. + if (mContent && mContent->OwnerDoc() && mContent->OwnerDoc()->GetWindow()) { + nsCOMPtr windowRoot = mContent->OwnerDoc()->GetWindow()->GetTopWindowRoot(); + if (windowRoot) { + windowRoot->AddEventListener(NS_LITERAL_STRING("activate"), + this, false, false); + windowRoot->AddEventListener(NS_LITERAL_STRING("deactivate"), + this, false, false); + windowRoot->AddEventListener(NS_LITERAL_STRING("MozPerformDelayedBlur"), + this, false, false); + } + } } } diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index a244430067f..acebe36ee40 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -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,14 +114,19 @@ public: nsresult Init(nsIContent* aContent); - void* GetPluginPortFromWidget(); + void* GetPluginPort(); void ReleasePluginPort(void* pluginPort); nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent); #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 *sCATimer; static nsTArray *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 diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index b040e32bdb1..4ba8c5448fc 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -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; } diff --git a/dom/plugins/ipc/PluginUtilsOSX.mm b/dom/plugins/ipc/PluginUtilsOSX.mm index 4973f7376da..1410cc9a422 100644 --- a/dom/plugins/ipc/PluginUtilsOSX.mm +++ b/dom/plugins/ipc/PluginUtilsOSX.mm @@ -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]; - // 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 setRemoteEvents:remoteEvent pluginModule:pluginModule]; - NSTimer *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]; + 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 alloc] init]; + [eventProcessor setRemoteEvents:remoteEvent pluginModule:pluginModule]; + 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(aMenu); NSPoint screen_point = ::NSMakePoint(aX, aY); [nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil]; - [eventTimer invalidate]; - [eventProcessor release]; + if (pluginModule) { + [eventTimer invalidate]; + [eventProcessor release]; + } return NPERR_NO_ERROR; diff --git a/dom/plugins/test/mochitest/cocoa_focus.html b/dom/plugins/test/mochitest/cocoa_focus.html index c3edbd7be05..57f132fa8d3 100644 --- a/dom/plugins/test/mochitest/cocoa_focus.html +++ b/dom/plugins/test/mochitest/cocoa_focus.html @@ -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(); diff --git a/dom/plugins/test/mochitest/test_convertpoint.xul b/dom/plugins/test/mochitest/test_convertpoint.xul index fcfe5943159..c121cf4d1d3 100644 --- a/dom/plugins/test/mochitest/test_convertpoint.xul +++ b/dom/plugins/test/mochitest/test_convertpoint.xul @@ -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; diff --git a/dom/plugins/test/testplugin/nptest.cpp b/dom/plugins/test/testplugin/nptest.cpp index 0bca444a2ee..d29c07a5677 100644 --- a/dom/plugins/test/testplugin/nptest.cpp +++ b/dom/plugins/test/testplugin/nptest.cpp @@ -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 diff --git a/dom/plugins/test/testplugin/nptest_macosx.mm b/dom/plugins/test/testplugin/nptest_macosx.mm index 8ffa5e85f36..d4a65ccfdd1 100644 --- a/dom/plugins/test/testplugin/nptest_macosx.mm +++ b/dom/plugins/test/testplugin/nptest_macosx.mm @@ -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) { diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 6fc9cd00cb8..091997580ee 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -2931,6 +2931,8 @@ nsRootPresContext::CancelApplyPluginGeometryTimer() } } +#ifndef XP_MACOSX + static bool HasOverlap(const nsIntPoint& aOffset1, const nsTArray& aClipRects1, const nsIntPoint& aOffset2, const nsTArray& aClipRects2) @@ -2999,18 +3001,6 @@ SortConfigurations(nsTArray* aConfigurations) } } -static PLDHashOperator -PluginDidSetGeometryEnumerator(nsRefPtrHashKey* aEntry, void* userArg) -{ - nsPluginFrame* f = static_cast(aEntry->GetKey()->GetPrimaryFrame()); - if (!f) { - NS_WARNING("Null frame in PluginDidSetGeometryEnumerator"); - return PL_DHASH_NEXT; - } - f->DidSetWidgetGeometry(); - return PL_DHASH_NEXT; -} - struct PluginGetGeometryUpdateClosure { nsTArray mConfigurations; }; @@ -3028,9 +3018,24 @@ PluginGetGeometryUpdate(nsRefPtrHashKey* aEntry, void* userArg) return PL_DHASH_NEXT; } +#endif // #ifndef XP_MACOSX + +static PLDHashOperator +PluginDidSetGeometryEnumerator(nsRefPtrHashKey* aEntry, void* userArg) +{ + nsPluginFrame* f = static_cast(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); } diff --git a/layout/generic/moz.build b/layout/generic/moz.build index 0d073ffb78d..3dc38b2525b 100644 --- a/layout/generic/moz.build +++ b/layout/generic/moz.build @@ -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 diff --git a/layout/generic/nsPluginFrame.cpp b/layout/generic/nsPluginFrame.cpp index 0abdfb304c1..64527073275 100644 --- a/layout/generic/nsPluginFrame.cpp +++ b/layout/generic/nsPluginFrame.cpp @@ -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,17 +1088,23 @@ nsPluginFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, } #endif - if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) { - NPWindow* window = nullptr; - mInstanceOwner->GetWindow(window); - bool isVisible = window && window->width > 0 && window->height > 0; - if (isVisible && aBuilder->ShouldSyncDecodeImages()) { - #ifndef XP_MACOSX - mInstanceOwner->UpdateWindowVisibility(true); - #endif - } + 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; + if (isVisible && aBuilder->ShouldSyncDecodeImages()) { +#ifndef XP_MACOSX + mInstanceOwner->UpdateWindowVisibility(true); +#endif + } - mInstanceOwner->NotifyPaintWaiter(aBuilder); + mInstanceOwner->NotifyPaintWaiter(aBuilder); + } } DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox @@ -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 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,13 +1859,7 @@ nsPluginFrame::EndSwapDocShells(nsISupports* aSupports, void*) } } -#ifdef XP_MACOSX - if (objectFrame->mWidget) { - objectFrame->RegisterPluginForGeometryUpdates(); - } -#else objectFrame->RegisterPluginForGeometryUpdates(); -#endif } nsIFrame* diff --git a/layout/generic/nsPluginFrame.h b/layout/generic/nsPluginFrame.h index accd0a1c607..4ff968c987c 100644 --- a/layout/generic/nsPluginFrame.h +++ b/layout/generic/nsPluginFrame.h @@ -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& 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) : diff --git a/layout/generic/nsPluginUtilsOSX.h b/layout/generic/nsPluginUtilsOSX.h deleted file mode 100644 index 8f7988d5025..00000000000 --- a/layout/generic/nsPluginUtilsOSX.h +++ /dev/null @@ -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 -#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); - diff --git a/layout/generic/nsPluginUtilsOSX.mm b/layout/generic/nsPluginUtilsOSX.mm deleted file mode 100644 index 8f7f3214e6c..00000000000 --- a/layout/generic/nsPluginUtilsOSX.mm +++ /dev/null @@ -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 -#import -#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; -} - diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index bfb539ec621..5fc4e2be370 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -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)); +} diff --git a/layout/generic/nsSubDocumentFrame.h b/layout/generic/nsSubDocumentFrame.h index c4414a32e6c..b6b5eb21e4b 100644 --- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -127,6 +127,8 @@ public: */ bool PassPointerEventsToChildren(); + nsIntPoint GetChromeDisplacement(); + protected: friend class AsyncFrameInit; diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp index 0a2c220feba..e28e36be3f5 100644 --- a/view/nsViewManager.cpp +++ b/view/nsViewManager.cpp @@ -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(); } diff --git a/widget/BasicEvents.h b/widget/BasicEvents.h index c898dc911d6..f55ce9bfafd 100644 --- a/widget/BasicEvents.h +++ b/widget/BasicEvents.h @@ -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 diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index aff7c5567f6..1177bd25cac 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -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) { diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h index c2258a304aa..60489452254 100644 --- a/widget/PuppetWidget.h +++ b/widget/PuppetWidget.h @@ -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; diff --git a/widget/TextEvents.h b/widget/TextEvents.h index a56f25df7ef..e9ec1d22349 100644 --- a/widget/TextEvents.h +++ b/widget/TextEvents.h @@ -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) { diff --git a/widget/WidgetEventImpl.cpp b/widget/WidgetEventImpl.cpp index fb54273db37..d8b8f27a665 100644 --- a/widget/WidgetEventImpl.cpp +++ b/widget/WidgetEventImpl.cpp @@ -191,8 +191,7 @@ WidgetEvent::IsUsingCoordinates() const return !HasKeyEventMessage() && !IsIMERelatedEvent() && !HasPluginActivationEventMessage() && !IsNativeEventDelivererForPlugin() && - !IsContentCommandEvent() && - message != NS_PLUGIN_RESOLUTION_CHANGED; + !IsContentCommandEvent(); } bool diff --git a/widget/cocoa/ComplexTextInputPanel.h b/widget/cocoa/ComplexTextInputPanel.h index d98329f943f..4cab3ba86ae 100644 --- a/widget/cocoa/ComplexTextInputPanel.h +++ b/widget/cocoa/ComplexTextInputPanel.h @@ -28,23 +28,19 @@ #ifndef ComplexTextInputPanel_h_ #define ComplexTextInputPanel_h_ -#import +#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_ diff --git a/widget/cocoa/ComplexTextInputPanel.mm b/widget/cocoa/ComplexTextInputPanel.mm index 2f932e4d10e..b8ddccfdd49 100644 --- a/widget/cocoa/ComplexTextInputPanel.mm +++ b/widget/cocoa/ComplexTextInputPanel.mm @@ -27,6 +27,8 @@ #import "ComplexTextInputPanel.h" +#import + #include #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( - 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(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)]; +} diff --git a/widget/cocoa/TextInputHandler.h b/widget/cocoa/TextInputHandler.h index 328fc1fefc8..3fa5b9f538b 100644 --- a/widget/cocoa/TextInputHandler.h +++ b/widget/cocoa/TextInputHandler.h @@ -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 *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); diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm index d850eabf856..56236540bcd 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -22,34 +22,6 @@ #include "WidgetUtils.h" #include "nsPrintfCString.h" -#ifdef __LP64__ -#include "ComplexTextInputPanel.h" -#include -#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); - keyEvent.mPluginEvent.Copy(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 *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 *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(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 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 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(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(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(widget)->GetTextInputHandler(); - if (handler) { - handler->SetPluginTSMInComposition(false); - } - } - } - [self PluginTextInputHandler_IMKInputSession_finishSession]; -} - -@end - -#endif // #ifndef __LP64__ - - -#pragma mark - - - /****************************************************************************** * * TextInputHandlerBase implementation diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build index 10f3421180c..37105db0b21 100644 --- a/widget/cocoa/moz.build +++ b/widget/cocoa/moz.build @@ -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' diff --git a/widget/cocoa/mozView.h b/widget/cocoa/mozView.h index 935cf9bf051..9e94e3ab4c4 100644 --- a/widget/cocoa/mozView.h +++ b/widget/cocoa/mozView.h @@ -6,8 +6,6 @@ #ifndef mozView_h_ #define mozView_h_ -#include "npapi.h" - #undef DARWIN #import 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. diff --git a/widget/cocoa/nsAppShell.mm b/widget/cocoa/nsAppShell.mm index e746d36f587..ce0da17a0a9 100644 --- a/widget/cocoa/nsAppShell.mm +++ b/widget/cocoa/nsAppShell.mm @@ -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." diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h index c93613987b3..dc62a5faf8f 100644 --- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -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 #import #import -// 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* 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 mGLPresenter; @@ -729,7 +638,4 @@ protected: void ReleaseTitlebarCGContext(); }; -void NS_InstallPluginKeyEventsHandler(); -void NS_RemovePluginKeyEventsHandler(); - #endif // nsChildView_h_ diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 56dc358985c..363428cfd6c 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -31,7 +31,6 @@ #include "nsILocalFileMac.h" #include "nsGfxCIID.h" #include "nsIDOMSimpleGestureEvent.h" -#include "nsNPAPIPluginInstance.h" #include "nsThemeConstants.h" #include "nsIWidgetListener.h" #include "nsIPresShell.h" @@ -44,9 +43,6 @@ #include "nsCocoaUtils.h" #include "nsMenuUtilsX.h" #include "nsMenuBarX.h" -#ifdef __LP64__ -#include "ComplexTextInputPanel.h" -#endif #include "NativeKeyBindings.h" #include "gfxContext.h" @@ -158,11 +154,6 @@ static uint32_t gNumberOfWidgetsNeedingEventThread = 0; - (NSMenu*)contextMenu; -- (void)setIsPluginView:(BOOL)aIsPlugin; -- (void)setPluginEventModel:(NPEventModel)eventModel; -- (void)setPluginDrawingModel:(NPDrawingModel)drawingModel; -- (NPDrawingModel)pluginDrawingModel; - - (BOOL)isRectObscuredBySubview:(NSRect)inRect; - (void)processPendingRedraws; @@ -462,13 +453,9 @@ nsChildView::nsChildView() : nsBaseWidget() , mBackingScaleFactor(0.0) , mVisible(false) , mDrawing(false) -, mPluginDrawing(false) , mIsDispatchPaint(false) -, mPluginInstanceOwner(nullptr) { EnsureLogInitialized(); - - memset(&mPluginCGContext, 0, sizeof(mPluginCGContext)); } nsChildView::~nsChildView() @@ -516,8 +503,6 @@ nsChildView::ReleaseTitlebarCGContext() } } -NS_IMPL_ISUPPORTS_INHERITED(nsChildView, nsBaseWidget, nsIPluginWidget) - nsresult nsChildView::Create(nsIWidget *aParent, nsNativeWidget aNativeParent, const nsIntRect &aRect, @@ -543,8 +528,6 @@ nsresult nsChildView::Create(nsIWidget *aParent, nsToolkit::SwizzleMethods([NSEvent class], @selector(removeMonitor:), @selector(nsChildView_NSEvent_removeMonitor:), true); } -#else - TextInputHandler::SwizzleMethods(); #endif gChildViewMethodsSwizzled = true; } @@ -581,8 +564,6 @@ nsresult nsChildView::Create(nsIWidget *aParent, return NS_ERROR_FAILURE; } - [(ChildView*)mView setIsPluginView:(mWindowType == eWindowType_plugin)]; - // If this view was created in a Gecko view hierarchy, the initial state // is hidden. If the view is attached only to a native NSView but has // no Gecko parent (as in embedding), the initial state is visible. @@ -739,18 +720,6 @@ void* nsChildView::GetNativeData(uint32_t aDataType) case NS_NATIVE_OFFSETY: retVal = 0; break; - - case NS_NATIVE_PLUGIN_PORT: - case NS_NATIVE_PLUGIN_PORT_CG: - { - // The NP_CGContext pointer should always be NULL in the Cocoa event model. - if ([(ChildView*)mView pluginEventModel] == NPEventModelCocoa) - return nullptr; - - UpdatePluginPort(); - retVal = (void*)&mPluginCGContext; - break; - } } return retVal; @@ -800,50 +769,6 @@ bool nsChildView::IsVisible() const NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); } -void nsChildView::HidePlugin() -{ - NS_ASSERTION(mWindowType == eWindowType_plugin, - "HidePlugin called on non-plugin view"); -} - -void nsChildView::UpdatePluginPort() -{ - NS_ASSERTION(mWindowType == eWindowType_plugin, - "UpdatePluginPort called on non-plugin view"); - - // [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. - mPluginCGContext.context = NULL; - mPluginCGContext.window = NULL; -} - -static void HideChildPluginViews(NSView* aView) -{ - NSArray* subviews = [aView subviews]; - - for (unsigned int i = 0; i < [subviews count]; ++i) { - NSView* view = [subviews objectAtIndex: i]; - - if (![view isKindOfClass:[ChildView class]]) - continue; - - ChildView* childview = static_cast(view); - if ([childview isPluginView]) { - nsChildView* widget = static_cast([childview widget]); - if (widget) { - widget->HidePlugin(); - } - } else { - HideChildPluginViews(view); - } - } -} - // Some NSView methods (e.g. setFrame and setHidden) invalidate the view's // bounds in our window. However, we don't want these invalidations because // they are unnecessary and because they actually slow us down since we @@ -883,8 +808,6 @@ NS_IMETHODIMP nsChildView::Show(bool aState) }); mVisible = aState; - if (!mVisible && IsPluginView()) - HidePlugin(); } return NS_OK; @@ -1042,7 +965,6 @@ NS_IMETHODIMP nsChildView::GetClientBounds(nsIntRect &aRect) if (!mParentWidget) { // For top level widgets we want the position on screen, not the position // of this view inside the window. - MOZ_ASSERT(mWindowType != eWindowType_plugin, "plugin widgets should have parents"); aRect.MoveTo(WidgetToScreenOffset()); } return NS_OK; @@ -1093,13 +1015,6 @@ nsChildView::BackingScaleFactorChanged() presShell->BackingScaleFactorChanged(); } } - - if (IsPluginView()) { - nsEventStatus status = nsEventStatus_eIgnore; - WidgetGUIEvent guiEvent(true, NS_PLUGIN_RESOLUTION_CHANGED, this); - guiEvent.time = PR_IntervalNow(); - DispatchEvent(&guiEvent, status); - } } int32_t @@ -1239,208 +1154,6 @@ bool nsChildView::ShowsResizeIndicator(nsIntRect* aResizerRect) return true; } -// In QuickDraw mode the coordinate system used here should be that of the -// browser window's content region (defined as everything but the 22-pixel -// high titlebar). But in CoreGraphics mode the coordinate system should be -// that of the browser window as a whole (including its titlebar). Both -// coordinate systems have a top-left origin. See bmo bug 474491. -// -// There's a bug in this method's code -- it currently uses the QuickDraw -// coordinate system for both the QuickDraw and CoreGraphics drawing modes. -// This bug is fixed by the patch for bug 474491. But the Flash plugin (both -// version 10.0.12.36 from Adobe and version 9.0 r151 from Apple) has Mozilla- -// specific code to work around this bug, which breaks when we fix it (see bmo -// bug 477077). So we'll need to coordinate releasing a fix for this bug with -// Adobe and other major plugin vendors that support the CoreGraphics mode. -// -// outClipRect and outOrigin are in display pixels, not device pixels. -NS_IMETHODIMP nsChildView::GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, bool& outWidgetVisible) -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NS_ASSERTION(mWindowType == eWindowType_plugin, - "GetPluginClipRect must only be called on a plugin widget"); - if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE; - - NSWindow* window = [mView window]; - if (!window) return NS_ERROR_FAILURE; - - NSPoint viewOrigin = [mView convertPoint:NSZeroPoint toView:nil]; - NSRect frame = [[window contentView] frame]; - viewOrigin.y = frame.size.height - viewOrigin.y; - - // set up the clipping region for plugins. - NSRect visibleBounds = [mView visibleRect]; - NSPoint clipOrigin = [mView convertPoint:visibleBounds.origin toView:nil]; - - // Convert from cocoa to QuickDraw coordinates - clipOrigin.y = frame.size.height - clipOrigin.y; - - outClipRect.x = NSToIntRound(clipOrigin.x); - outClipRect.y = NSToIntRound(clipOrigin.y); - - // need to convert view's origin to window coordinates. - // then, encode as "SetOrigin" ready values. - outOrigin.x = -NSToIntRound(viewOrigin.x); - outOrigin.y = -NSToIntRound(viewOrigin.y); - - if (IsVisible() && [mView window] != nil) { - outClipRect.width = NSToIntRound(visibleBounds.origin.x + visibleBounds.size.width) - NSToIntRound(visibleBounds.origin.x); - outClipRect.height = NSToIntRound(visibleBounds.origin.y + visibleBounds.size.height) - NSToIntRound(visibleBounds.origin.y); - - if (mClipRects) { - nsIntRect clipBounds; - for (uint32_t i = 0; i < mClipRectCount; ++i) { - NSRect cocoaPoints = DevPixelsToCocoaPoints(mClipRects[i]); - clipBounds.UnionRect(clipBounds, nsIntRect(NSToIntRound(cocoaPoints.origin.x), - NSToIntRound(cocoaPoints.origin.y), - NSToIntRound(cocoaPoints.size.width), - NSToIntRound(cocoaPoints.size.height))); - } - outClipRect.IntersectRect(outClipRect, clipBounds - outOrigin); - } - - // XXXroc should this be !outClipRect.IsEmpty()? - outWidgetVisible = true; - } - else { - outClipRect.width = 0; - outClipRect.height = 0; - outWidgetVisible = false; - } - - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsChildView::StartDrawPlugin() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - - NS_ASSERTION(mWindowType == eWindowType_plugin, - "StartDrawPlugin must only be called on a plugin widget"); - if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE; - - // This code is necessary for CoreGraphics in 32-bit builds. - // See comments below about why. In 64-bit CoreGraphics mode we will not keep - // this region up to date, plugins should not depend on it. -#ifndef __LP64__ - NSWindow* window = [mView window]; - if (!window) - return NS_ERROR_FAILURE; - - // In QuickDraw drawing mode we used to prevent reentrant handling of any - // plugin event. 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 (mIsDispatchPaint && 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 - // we don't know here if we're being drawn inside a BeginUpdate/EndUpdate pair - // (which seem to occur in [NSWindow display]), and we don't want to have the burden - // of correctly doing Carbon invalidates of the plugin rect, we manually set the - // visible region to be the entire port every time. It is necessary to set up our - // window's port even for CoreGraphics plugins, because they may still use Carbon - // internally (see bug #420527 for details). - // - // 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 (::NewRgn && ::GetQDGlobalsThePort && ::GetGWorld && ::SetGWorld && - ::IsPortOffscreen && ::GetMainDevice && ::SetOrigin && ::RectRgn && - ::SetPortVisibleRegion && ::SetPortClipRegion && ::DisposeRgn) { - RgnHandle pluginRegion = ::NewRgn(); - if (pluginRegion) { - CGrafPtr port = ::GetWindowPort(WindowRef([window windowRef])); - bool portChanged = (port != CGrafPtr(::GetQDGlobalsThePort())); - CGrafPtr oldPort; - GDHandle oldDevice; - - if (portChanged) { - ::GetGWorld(&oldPort, &oldDevice); - ::SetGWorld(port, ::IsPortOffscreen(port) ? nullptr : ::GetMainDevice()); - } - - ::SetOrigin(0, 0); - - nsIntRect clipRect; // this is in native window coordinates - nsIntPoint origin; - bool visible; - GetPluginClipRect(clipRect, origin, visible); - - // XXX if we're not visible, set an empty clip region? - Rect pluginRect; - ConvertGeckoRectToMacRect(clipRect, pluginRect); - - ::RectRgn(pluginRegion, &pluginRect); - ::SetPortVisibleRegion(port, pluginRegion); - ::SetPortClipRegion(port, pluginRegion); - - // now set up the origin for the plugin - ::SetOrigin(origin.x, origin.y); - - ::DisposeRgn(pluginRegion); - - if (portChanged) { - ::SetGWorld(oldPort, oldDevice); - } - } - } -#endif - - mPluginDrawing = true; - return NS_OK; - - NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; -} - -NS_IMETHODIMP nsChildView::EndDrawPlugin() -{ - NS_ASSERTION(mWindowType == eWindowType_plugin, - "EndDrawPlugin must only be called on a plugin widget"); - if (mWindowType != eWindowType_plugin) return NS_ERROR_FAILURE; - - mPluginDrawing = false; - return NS_OK; -} - -NS_IMETHODIMP nsChildView::SetPluginInstanceOwner(nsIPluginInstanceOwner* aInstanceOwner) -{ - mPluginInstanceOwner = aInstanceOwner; - - return NS_OK; -} - -NS_IMETHODIMP nsChildView::SetPluginEventModel(int inEventModel) -{ - [(ChildView*)mView setPluginEventModel:(NPEventModel)inEventModel]; - return NS_OK; -} - -NS_IMETHODIMP nsChildView::GetPluginEventModel(int* outEventModel) -{ - *outEventModel = [(ChildView*)mView pluginEventModel]; - return NS_OK; -} - -NS_IMETHODIMP nsChildView::SetPluginDrawingModel(int inDrawingModel) -{ - [(ChildView*)mView setPluginDrawingModel:(NPDrawingModel)inDrawingModel]; - return NS_OK; -} - -NS_IMETHODIMP nsChildView::StartComplexTextInputForCurrentEvent() -{ - return mTextInputHandler->StartComplexTextInputForCurrentEvent(); -} - nsresult nsChildView::SynthesizeNativeKeyEvent(int32_t aNativeKeyboardLayout, int32_t aNativeKeyCode, uint32_t aModifierFlags, @@ -1460,8 +1173,10 @@ nsresult nsChildView::SynthesizeNativeMouseEvent(nsIntPoint aPoint, { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; - NSPoint pt = - nsCocoaUtils::DevPixelsToCocoaPoints(aPoint, BackingScaleFactor()); + // We want Cocoa 'points' (where there is a 1:1 mapping from pixels on low-DPI + // devices and a 4:1 mapping from pixels on retina devices). These correspond + // to Gecko device pixels, which is what we are given. + NSPoint pt = NSMakePoint(aPoint.x, aPoint.y); // Move the mouse cursor to the requested position and reconnect it to the mouse. CGWarpMouseCursorPosition(NSPointToCGPoint(pt)); @@ -1694,29 +1409,6 @@ inline uint16_t COLOR8TOCOLOR16(uint8_t color8) nsresult nsChildView::ConfigureChildren(const nsTArray& aConfigurations) { - for (uint32_t i = 0; i < aConfigurations.Length(); ++i) { - const Configuration& config = aConfigurations[i]; - nsChildView* child = static_cast(config.mChild); -#ifdef DEBUG - nsWindowType kidType = child->WindowType(); -#endif - NS_ASSERTION(kidType == eWindowType_plugin, - "Configured widget is not a plugin type"); - NS_ASSERTION(child->GetParent() == this, - "Configured widget is not a child of the right widget"); - - // nsIWidget::Show() doesn't get called on plugin widgets unless we call - // it from here. See bug 592563. - child->Show(!config.mClipRegion.IsEmpty()); - - child->Resize( - config.mBounds.x, config.mBounds.y, - config.mBounds.width, config.mBounds.height, - false); - - // Store the clip region here in case GetPluginClipRect needs it. - child->StoreWindowClipRegion(config.mClipRegion); - } return NS_OK; } @@ -3226,21 +2918,6 @@ NSEvent* gLastDragMouseDownEvent = nil; if ((self = [super initWithFrame:inFrame])) { mGeckoChild = inChild; - mIsPluginView = NO; -#ifndef NP_NO_CARBON - // We don't support the Carbon event model but it's still the default - // model for i386 per NPAPI. - mPluginEventModel = NPEventModelCarbon; -#else - mPluginEventModel = NPEventModelCocoa; -#endif -#ifndef NP_NO_QUICKDRAW - // We don't support the Quickdraw drawing model any more but it's still - // the default model for i386 per NPAPI. - mPluginDrawingModel = NPDrawingModelQuickDraw; -#else - mPluginDrawingModel = NPDrawingModelCoreGraphics; -#endif mPendingDisplay = NO; mBlockedLastMouseDown = NO; mExpectingWheelStop = NO; @@ -3272,14 +2949,6 @@ NSEvent* gLastDragMouseDownEvent = nil; // register for things we'll take from other applications [ChildView registerViewForDraggedTypes:self]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowBecameMain:) - name:NSWindowDidBecomeMainNotification - object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowResignedMain:) - name:NSWindowDidResignMainNotification - object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(systemMetricsChanged) name:NSControlTintDidChangeNotification @@ -3397,46 +3066,6 @@ NSEvent* gLastDragMouseDownEvent = nil; NS_OBJC_END_TRY_ABORT_BLOCK; } -- (void)updatePluginTopLevelWindowStatus:(BOOL)hasMain -{ - if (!mGeckoChild) - return; - - WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, mGeckoChild); - NPCocoaEvent cocoaEvent; - nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent); - cocoaEvent.type = NPCocoaEventWindowFocusChanged; - cocoaEvent.data.focus.hasFocus = hasMain; - nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent); - mGeckoChild->DispatchWindowEvent(pluginEvent); -} - -- (void)windowBecameMain:(NSNotification*)inNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) { - if ((NSWindow*)[inNotification object] == [self window]) { - [self updatePluginTopLevelWindowStatus:YES]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)windowResignedMain:(NSNotification*)inNotification -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) { - if ((NSWindow*)[inNotification object] == [self window]) { - [self updatePluginTopLevelWindowStatus:NO]; - } - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - - (void)widgetDestroyed { if (mTextInputHandler) { @@ -3568,90 +3197,7 @@ NSEvent* gLastDragMouseDownEvent = nil; - (BOOL)isOpaque { - return [[self window] isOpaque] && !mIsPluginView; -} - --(void)setIsPluginView:(BOOL)aIsPlugin -{ - mIsPluginView = aIsPlugin; -} - --(BOOL)isPluginView -{ - return mIsPluginView; -} - -- (NSView *)hitTest:(NSPoint)aPoint -{ - NSView* target = [super hitTest:aPoint]; - if ((target == self) && [self isPluginView] && mGeckoChild) { - nsAutoRetainCocoaObject kungFuDeathGrip(self); - - NSPoint cocoaLoc = [[self superview] convertPoint:aPoint toView:self]; - LayoutDeviceIntPoint widgetLoc = LayoutDeviceIntPoint::FromUntyped( - mGeckoChild->CocoaPointsToDevPixels(cocoaLoc)); - - WidgetQueryContentEvent hitTest(true, NS_QUERY_DOM_WIDGET_HITTEST, - mGeckoChild); - hitTest.InitForQueryDOMWidgetHittest(widgetLoc); - // This might destroy our widget. - mGeckoChild->DispatchWindowEvent(hitTest); - if (!mGeckoChild) { - return nil; - } - if (hitTest.mSucceeded && !hitTest.mReply.mWidgetIsHit) { - return nil; - } - } - return target; -} - -// Are we processing an NSLeftMouseDown event that will fail to click through? -// If so, we shouldn't focus or unfocus a plugin. -- (BOOL)isInFailingLeftClickThrough -{ - if (!mGeckoChild) - return NO; - - if (!mClickThroughMouseDownEvent || - [mClickThroughMouseDownEvent type] != NSLeftMouseDown) - return NO; - - BOOL retval = - !ChildViewMouseTracker::WindowAcceptsEvent([self window], - mClickThroughMouseDownEvent, - self, true); - - // If we return YES here, this will result in us not being focused, - // which will stop us receiving mClickThroughMouseDownEvent in - // [ChildView mouseDown:]. So we need to release and null-out - // mClickThroughMouseDownEvent here. - if (retval) { - [mClickThroughMouseDownEvent release]; - mClickThroughMouseDownEvent = nil; - } - - return retval; -} - -- (void)setPluginEventModel:(NPEventModel)eventModel -{ - mPluginEventModel = eventModel; -} - -- (void)setPluginDrawingModel:(NPDrawingModel)drawingModel -{ - mPluginDrawingModel = drawingModel; -} - -- (NPEventModel)pluginEventModel -{ - return mPluginEventModel; -} - -- (NPDrawingModel)pluginDrawingModel -{ - return mPluginDrawingModel; + return [[self window] isOpaque]; } - (void)sendFocusEvent:(uint32_t)eventType @@ -3686,28 +3232,6 @@ NSEvent* gLastDragMouseDownEvent = nil; return YES; } -- (void)viewWillMoveToWindow:(NSWindow *)newWindow -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!newWindow) - HideChildPluginViews(self); - - [super viewWillMoveToWindow:newWindow]; - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - -- (void)viewDidMoveToWindow -{ - if (mPluginEventModel == NPEventModelCocoa && - [self window] && [self isPluginView] && mGeckoChild) { - mGeckoChild->UpdatePluginPort(); - } - - [super viewDidMoveToWindow]; -} - - (void)scrollRect:(NSRect)aRect by:(NSSize)offset { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; @@ -3826,10 +3350,6 @@ NSEvent* gLastDragMouseDownEvent = nil; if (!mGeckoChild || !mGeckoChild->IsVisible()) return; - // Don't ever draw plugin views explicitly; they'll be drawn as part of their parent widget. - if (mIsPluginView) - return; - #ifdef DEBUG_UPDATE nsIntRect geckoBounds; mGeckoChild->GetBounds(geckoBounds); @@ -4924,16 +4444,6 @@ NSEvent* gLastDragMouseDownEvent = nil; else geckoEvent.button = WidgetMouseEvent::eLeftButton; - // 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. - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseDown, - &cocoaEvent); - // Don't lose possible changes made above to clickCount - cocoaEvent.data.mouse.clickCount = clickCount; - mGeckoChild->DispatchWindowEvent(geckoEvent); mBlockedLastMouseDown = NO; @@ -4951,8 +4461,6 @@ NSEvent* gLastDragMouseDownEvent = nil; nsAutoRetainCocoaObject kungFuDeathGrip(self); - NPCocoaEvent cocoaEvent; - WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGeckoChild, WidgetMouseEvent::eReal); [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; @@ -4961,13 +4469,6 @@ NSEvent* gLastDragMouseDownEvent = nil; else geckoEvent.button = WidgetMouseEvent::eLeftButton; - // 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. - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseUp, - &cocoaEvent); - // This might destroy our widget (and null out mGeckoChild). bool defaultPrevented = mGeckoChild->DispatchWindowEvent(geckoEvent); @@ -4987,13 +4488,6 @@ NSEvent* gLastDragMouseDownEvent = nil; } } - // If our mouse-up event's location is over some other object (as might - // happen if it came at the end of a dragging operation), also send our - // Gecko frame a mouse-exit event. - if (mGeckoChild && mIsPluginView) { - ChildViewMouseTracker::ReEvaluateMouseEnterState(theEvent, self); - } - NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -5012,15 +4506,6 @@ NSEvent* gLastDragMouseDownEvent = nil; event.refPoint = LayoutDeviceIntPoint::FromUntyped( mGeckoChild->CocoaPointsToDevPixels(localEventLocation)); - // 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. - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(event, self, aEvent, - (msg == NS_MOUSE_ENTER) ? - NPCocoaEventMouseEntered : NPCocoaEventMouseExited, - &cocoaEvent); - event.exit = aType; nsEventStatus status; // ignored @@ -5111,13 +4596,6 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, WidgetMouseEvent::eReal); [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - // 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. - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseMoved, - &cocoaEvent); mGeckoChild->DispatchWindowEvent(geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; @@ -5132,17 +4610,10 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, gLastDragView = self; - NPCocoaEvent cocoaEvent; - WidgetMouseEvent geckoEvent(true, NS_MOUSE_MOVE, mGeckoChild, WidgetMouseEvent::eReal); [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; - // create event for use by plugins - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseDragged, - &cocoaEvent); - mGeckoChild->DispatchWindowEvent(geckoEvent); // Note, sending the above event might have destroyed our widget since we didn't retain. @@ -5171,12 +4642,6 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, geckoEvent.button = WidgetMouseEvent::eRightButton; geckoEvent.clickCount = [theEvent clickCount]; - // create event for use by plugins - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseDown, - &cocoaEvent); - mGeckoChild->DispatchWindowEvent(geckoEvent); if (!mGeckoChild) return; @@ -5194,29 +4659,15 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, if (!mGeckoChild) return; - NPCocoaEvent cocoaEvent; - WidgetMouseEvent geckoEvent(true, NS_MOUSE_BUTTON_UP, mGeckoChild, WidgetMouseEvent::eReal); [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; geckoEvent.button = WidgetMouseEvent::eRightButton; geckoEvent.clickCount = [theEvent clickCount]; - // create event for use by plugins - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseUp, - &cocoaEvent); - nsAutoRetainCocoaObject kungFuDeathGrip(self); mGeckoChild->DispatchWindowEvent(geckoEvent); - // If our mouse-up event's location is over some other object (as might - // happen if it came at the end of a dragging operation), also send our - // Gecko frame a mouse-exit event. - if (mGeckoChild && mIsPluginView) { - ChildViewMouseTracker::ReEvaluateMouseEnterState(theEvent, self); - } - NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -5230,12 +4681,6 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; geckoEvent.button = WidgetMouseEvent::eRightButton; - // create event for use by plugins - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseDragged, - &cocoaEvent); - // send event into Gecko by going directly to the // the widget. mGeckoChild->DispatchWindowEvent(geckoEvent); @@ -5260,12 +4705,6 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, geckoEvent.button = WidgetMouseEvent::eMiddleButton; geckoEvent.clickCount = [theEvent clickCount]; - // create event for use by plugins - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseDown, - &cocoaEvent); - mGeckoChild->DispatchWindowEvent(geckoEvent); NS_OBJC_END_TRY_ABORT_BLOCK; @@ -5281,21 +4720,8 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; geckoEvent.button = WidgetMouseEvent::eMiddleButton; - // create event for use by plugins - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseUp, - &cocoaEvent); - nsAutoRetainCocoaObject kungFuDeathGrip(self); mGeckoChild->DispatchWindowEvent(geckoEvent); - - // If our mouse-up event's location is over some other object (as might - // happen if it came at the end of a dragging operation), also send our - // Gecko frame a mouse-exit event. - if (mGeckoChild && mIsPluginView) { - ChildViewMouseTracker::ReEvaluateMouseEnterState(theEvent, self); - } } - (void)otherMouseDragged:(NSEvent*)theEvent @@ -5308,12 +4734,6 @@ NewCGSRegionFromRegion(const nsIntRegion& aRegion, [self convertCocoaMouseEvent:theEvent toGeckoEvent:&geckoEvent]; geckoEvent.button = WidgetMouseEvent::eMiddleButton; - // create event for use by plugins - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(geckoEvent, self, theEvent, - NPCocoaEventMouseDragged, - &cocoaEvent); - // send event into Gecko by going directly to the // the widget. mGeckoChild->DispatchWindowEvent(geckoEvent); @@ -5402,11 +4822,6 @@ static int32_t RoundUp(double aDouble) return; } - NPCocoaEvent cocoaEvent; - ChildViewMouseTracker::AttachPluginEvent(wheelEvent, self, theEvent, - NPCocoaEventScrollWheel, - &cocoaEvent); - mGeckoChild->DispatchWindowEvent(wheelEvent); if (!mGeckoChild) { return; @@ -5526,7 +4941,7 @@ static int32_t RoundUp(double aDouble) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; - if (!mGeckoChild || [self isPluginView]) + if (!mGeckoChild) return nil; nsAutoRetainCocoaObject kungFuDeathGrip(self); @@ -5870,16 +5285,6 @@ static int32_t RoundUp(double aDouble) #pragma mark - -#ifdef __LP64__ -- (NSTextInputContext *)inputContext -{ - if (mIsPluginView && mPluginEventModel == NPEventModelCocoa) - return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext]; - else - return [super inputContext]; -} -#endif - // This is a private API that Cocoa uses. // Cocoa will call this after the menu system returns "NO" for "performKeyEquivalent:". // We want all they key events we can get so just return YES. In particular, this fixes @@ -5914,18 +5319,7 @@ static int32_t RoundUp(double aDouble) [NSApp isActive]]; nsAutoCString additionalInfo([info UTF8String]); #endif - if (mIsPluginView) { - if (TextInputHandler::IsSecureEventInputEnabled()) { - #define CRASH_MESSAGE "While a plugin has focus, we must not be in secure mode" -#ifdef MOZ_CRASHREPORTER - CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("\nBug 893973: ") + - NS_LITERAL_CSTRING(CRASH_MESSAGE)); - CrashReporter::AppendAppNotesToCrashReport(additionalInfo); -#endif - MOZ_CRASH(CRASH_MESSAGE); - #undef CRASH_MESSAGE - } - } else if (mGeckoChild->GetInputContext().IsPasswordEditor() && + if (mGeckoChild->GetInputContext().IsPasswordEditor() && !TextInputHandler::IsSecureEventInputEnabled()) { #define CRASH_MESSAGE "A password editor has focus, but not in secure input mode" #ifdef MOZ_CRASHREPORTER @@ -5949,11 +5343,6 @@ static int32_t RoundUp(double aDouble) } #endif // #if !defined(RELEASE_BUILD) || defined(DEBUG) - if (mGeckoChild && mTextInputHandler && mIsPluginView) { - mTextInputHandler->HandleKeyDownEventForPlugin(theEvent); - return; - } - nsAutoRetainCocoaObject kungFuDeathGrip(self); bool handled = false; if (mGeckoChild && mTextInputHandler) { @@ -5977,11 +5366,6 @@ static int32_t RoundUp(double aDouble) nsAutoRetainCocoaObject kungFuDeathGrip(self); - if (mIsPluginView) { - mTextInputHandler->HandleKeyUpEventForPlugin(theEvent); - return; - } - mTextInputHandler->HandleKeyUpEvent(theEvent); NS_OBJC_END_TRY_ABORT_BLOCK; @@ -6031,60 +5415,17 @@ static int32_t RoundUp(double aDouble) return !mGeckoChild->DispatchWindowEvent(geckoEvent); } -// Returns NO if the plugin shouldn't be focused/unfocused. -- (BOOL)updatePluginFocusStatus:(BOOL)getFocus -{ - if (!mGeckoChild) - return NO; - - if (mPluginEventModel == NPEventModelCocoa) { - WidgetPluginEvent pluginEvent(true, NS_PLUGIN_FOCUS_EVENT, mGeckoChild); - NPCocoaEvent cocoaEvent; - nsCocoaUtils::InitNPCocoaEvent(&cocoaEvent); - cocoaEvent.type = NPCocoaEventFocusChanged; - cocoaEvent.data.focus.hasFocus = getFocus; - nsCocoaUtils::InitPluginEvent(pluginEvent, cocoaEvent); - mGeckoChild->DispatchWindowEvent(pluginEvent); - - if (getFocus) - [self sendFocusEvent:NS_PLUGIN_FOCUS]; - } - - return YES; -} - // We must always call through to our superclass, even when mGeckoChild is // nil -- otherwise the keyboard focus can end up in the wrong NSView. - (BOOL)becomeFirstResponder { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - if (mIsPluginView) { - if (![self updatePluginFocusStatus:YES]) - return NO; - } - return [super becomeFirstResponder]; NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES); } -// We must always call through to our superclass, even when mGeckoChild is -// nil -- otherwise the keyboard focus can end up in the wrong NSView. -- (BOOL)resignFirstResponder -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; - - if (mIsPluginView) { - if (![self updatePluginFocusStatus:NO]) - return NO; - } - - return [super resignFirstResponder]; - - NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(YES); -} - - (void)viewsWindowDidBecomeKey { NS_OBJC_BEGIN_TRY_ABORT_BLOCK; @@ -6871,56 +6212,6 @@ ChildViewMouseTracker::ViewForEvent(NSEvent* aEvent) return WindowAcceptsEvent(window, aEvent, childView) ? childView : nil; } -void -ChildViewMouseTracker::AttachPluginEvent(WidgetMouseEventBase& aMouseEvent, - ChildView* aView, - NSEvent* aNativeMouseEvent, - int aPluginEventType, - void* aPluginEventHolder) -{ - if (![aView isPluginView] || - [aView pluginEventModel] != NPEventModelCocoa) { - return; - } - - NPCocoaEvent* cocoaEvent = (NPCocoaEvent*)aPluginEventHolder; - nsCocoaUtils::InitNPCocoaEvent(cocoaEvent); - NSPoint point = [aView convertPoint:[aNativeMouseEvent locationInWindow] - fromView:nil]; - NPCocoaEventType type = (NPCocoaEventType)aPluginEventType; - // XXX We should consider dropping this code, which causes data.mouse.pluginX - // and data.mouse.pluginY to be set to '5' for mouse-entered and mouse-exited - // events. But note that it's been in the tree since the Cocoa NPAPI event - // model was first implemented four years ago, without any known complaints. - // - // Similar code first appeared (without explanation) in a very early version - // ("fix 0.3") of the patch for bug 435041 ("Implement Cocoa NPAPI event - // model for Mac OS X"). But there's no trace of it in the WebKit code that - // was used as a model for much of that patch. -#if (0) - if (type == NPCocoaEventMouseEntered || - type == NPCocoaEventMouseExited) { - point.x = point.y = 5; - } -#endif - NSUInteger clickCount = 0; - if (type != NPCocoaEventMouseEntered && - type != NPCocoaEventMouseExited && - type != NPCocoaEventScrollWheel) { - clickCount = [aNativeMouseEvent clickCount]; - } - cocoaEvent->type = type; - cocoaEvent->data.mouse.modifierFlags = [aNativeMouseEvent modifierFlags]; - cocoaEvent->data.mouse.pluginX = point.x; - cocoaEvent->data.mouse.pluginY = point.y; - cocoaEvent->data.mouse.buttonNumber = [aNativeMouseEvent buttonNumber]; - cocoaEvent->data.mouse.clickCount = clickCount; - cocoaEvent->data.mouse.deltaX = [aNativeMouseEvent deltaX]; - cocoaEvent->data.mouse.deltaY = [aNativeMouseEvent deltaY]; - cocoaEvent->data.mouse.deltaZ = [aNativeMouseEvent deltaZ]; - aMouseEvent.mPluginEvent.Copy(*cocoaEvent); -} - BOOL ChildViewMouseTracker::WindowAcceptsEvent(NSWindow* aWindow, NSEvent* aEvent, ChildView* aView, BOOL aIsClickThrough) diff --git a/widget/cocoa/nsCocoaFeatures.h b/widget/cocoa/nsCocoaFeatures.h index 18db925ae61..bb0ebcb4f31 100644 --- a/widget/cocoa/nsCocoaFeatures.h +++ b/widget/cocoa/nsCocoaFeatures.h @@ -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); diff --git a/widget/cocoa/nsCocoaFeatures.mm b/widget/cocoa/nsCocoaFeatures.mm index 67e02d98e21..ca84e9bf309 100644 --- a/widget/cocoa/nsCocoaFeatures.mm +++ b/widget/cocoa/nsCocoaFeatures.mm @@ -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() { diff --git a/widget/cocoa/nsCocoaUtils.h b/widget/cocoa/nsCocoaUtils.h index 57e26d4298c..99c235da503 100644 --- a/widget/cocoa/nsCocoaUtils.h +++ b/widget/cocoa/nsCocoaUtils.h @@ -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. */ diff --git a/widget/cocoa/nsCocoaUtils.mm b/widget/cocoa/nsCocoaUtils.mm index 732fb4ed097..721ebf4b8bc 100644 --- a/widget/cocoa/nsCocoaUtils.mm +++ b/widget/cocoa/nsCocoaUtils.mm @@ -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, diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 221e1f20513..f09022f3f5b 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -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(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; } } diff --git a/widget/cocoa/nsMenuBarX.mm b/widget/cocoa/nsMenuBarX.mm index 66e4bb99276..97fce76210a 100644 --- a/widget/cocoa/nsMenuBarX.mm +++ b/widget/cocoa/nsMenuBarX.mm @@ -832,40 +832,17 @@ 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; - } + if (![NSApp keyWindow] || [[NSApp keyWindow] firstResponder] != firstResponder) { + return YES; } // Return NO so that we can handle the event via NSView's "keyDown:". diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h index ddd6f7ff742..82b9ceec5fd 100644 --- a/widget/nsGUIEventIPC.h +++ b/widget/nsGUIEventIPC.h @@ -331,6 +331,12 @@ struct ParamTraits 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 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(keyNameIndex); aResult->mCodeNameIndex =