From 881c04e39072a339ade66e7f88ca7d8d642bfc87 Mon Sep 17 00:00:00 2001 From: Steven Michaud Date: Tue, 16 Oct 2012 20:41:21 +0100 Subject: [PATCH] bug 794038 pt 3 - plugins support for resolution change. r=bgirard --- dom/plugins/base/PluginPRLibrary.cpp | 7 ++++++ dom/plugins/base/PluginPRLibrary.h | 1 + dom/plugins/base/nsNPAPIPluginInstance.cpp | 20 +++++++++++++++++ dom/plugins/base/nsNPAPIPluginInstance.h | 1 + dom/plugins/base/nsPluginInstanceOwner.cpp | 8 +++++++ dom/plugins/base/nsPluginInstanceOwner.h | 1 + dom/plugins/ipc/PPluginInstance.ipdl | 3 +++ dom/plugins/ipc/PluginInstanceChild.cpp | 22 ++++++++++++++++++- dom/plugins/ipc/PluginInstanceChild.h | 3 +++ dom/plugins/ipc/PluginInstanceParent.cpp | 9 +++++++- dom/plugins/ipc/PluginInstanceParent.h | 1 + dom/plugins/ipc/PluginLibrary.h | 1 + dom/plugins/ipc/PluginModuleParent.cpp | 12 ++++++++++- dom/plugins/ipc/PluginModuleParent.h | 1 + dom/plugins/ipc/PluginUtilsOSX.h | 2 ++ dom/plugins/ipc/PluginUtilsOSX.mm | 16 ++++++++++++++ gfx/2d/QuartzSupport.mm | 25 +++++++++++++++++++++- layout/generic/nsObjectFrame.cpp | 9 ++++++++ view/src/nsViewManager.cpp | 3 ++- widget/cocoa/nsChildView.mm | 15 ++++++++----- widget/nsGUIEvent.h | 8 ++++++- 21 files changed, 157 insertions(+), 11 deletions(-) diff --git a/dom/plugins/base/PluginPRLibrary.cpp b/dom/plugins/base/PluginPRLibrary.cpp index c86566d6eef0..05bc33a8a6ff 100644 --- a/dom/plugins/base/PluginPRLibrary.cpp +++ b/dom/plugins/base/PluginPRLibrary.cpp @@ -277,6 +277,13 @@ PluginPRLibrary::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) *aDrawing = false; return NS_OK; } +nsresult +PluginPRLibrary::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) +{ + nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata; + NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER); + return NS_OK; +} #endif nsresult diff --git a/dom/plugins/base/PluginPRLibrary.h b/dom/plugins/base/PluginPRLibrary.h index f9b25b97bf36..7ba24719cb44 100644 --- a/dom/plugins/base/PluginPRLibrary.h +++ b/dom/plugins/base/PluginPRLibrary.h @@ -114,6 +114,7 @@ public: virtual bool IsOOP() MOZ_OVERRIDE { return false; } #if defined(XP_MACOSX) virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing); + virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor); #endif virtual nsresult SetBackgroundUnknown(NPP instance) MOZ_OVERRIDE; virtual nsresult BeginUpdateBackground(NPP instance, diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index 5fb754c0fed7..444c415f4595 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -1081,6 +1081,26 @@ nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing) #endif } +nsresult nsNPAPIPluginInstance::ContentsScaleFactorChanged(double aContentsScaleFactor) +{ +#ifdef XP_MACOSX + if (!mPlugin) + return NS_ERROR_FAILURE; + + PluginLibrary* library = mPlugin->GetLibrary(); + if (!library) + return NS_ERROR_FAILURE; + + // We only need to call this if the plugin is running OOP. + if (!library->IsOOP()) + return NS_OK; + + return library->ContentsScaleFactorChanged(&mNPP, aContentsScaleFactor); +#else + return NS_ERROR_FAILURE; +#endif +} + nsresult nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject) { diff --git a/dom/plugins/base/nsNPAPIPluginInstance.h b/dom/plugins/base/nsNPAPIPluginInstance.h index 31d66d1168a5..b94217accfe4 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -78,6 +78,7 @@ public: nsresult GetValueFromPlugin(NPPVariable variable, void* value); nsresult GetDrawingModel(int32_t* aModel); nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing); + nsresult ContentsScaleFactorChanged(double aContentsScaleFactor); nsresult GetJSObject(JSContext *cx, JSObject** outObject); bool ShouldCache(); nsresult IsWindowless(bool* isWindowless); diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index 3f5688320000..a47d002ea4f9 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1370,6 +1370,14 @@ bool nsPluginInstanceOwner::IsRemoteDrawingCoreAnimation() return coreAnimation; } +nsresult nsPluginInstanceOwner::ContentsScaleFactorChanged(double aContentsScaleFactor) +{ + if (!mInstance) { + return NS_ERROR_NULL_POINTER; + } + return mInstance->ContentsScaleFactorChanged(aContentsScaleFactor); +} + NPEventModel nsPluginInstanceOwner::GetEventModel() { return mEventModel; diff --git a/dom/plugins/base/nsPluginInstanceOwner.h b/dom/plugins/base/nsPluginInstanceOwner.h index dedb8da5ab62..e4fcf4cb92d1 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -116,6 +116,7 @@ public: NPDrawingModel GetDrawingModel(); bool IsRemoteDrawingCoreAnimation(); + nsresult ContentsScaleFactorChanged(double aContentsScaleFactor); NPEventModel GetEventModel(); static void CARefresh(nsITimer *aTimer, void *aClosure); void AddToCARefreshTimer(); diff --git a/dom/plugins/ipc/PPluginInstance.ipdl b/dom/plugins/ipc/PPluginInstance.ipdl index e50704bebef5..4013c1bafc1a 100644 --- a/dom/plugins/ipc/PPluginInstance.ipdl +++ b/dom/plugins/ipc/PPluginInstance.ipdl @@ -118,6 +118,9 @@ child: returns (int16_t handled); // this is only used on windows to forward WM_WINDOWPOSCHANGE async WindowPosChanged(NPRemoteEvent event); + // used on OS X to tell the child the contents scale factor + // of its parent has changed + async ContentsScaleFactorChanged(double aContentsScaleFactor); // ********************** Async plugins rendering // see https://wiki.mozilla.org/Gecko:AsyncPluginPainting diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index 8028a3465892..a53e5f798aa4 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -1013,6 +1013,24 @@ PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event) #endif } +bool +PluginInstanceChild::RecvContentsScaleFactorChanged(const double& aContentsScaleFactor) +{ +#ifdef XP_MACOSX + mContentsScaleFactor = aContentsScaleFactor; + if (mShContext) { + // Release the shared context so that it is reallocated + // with the new size. + ::CGContextRelease(mShContext); + mShContext = nullptr; + } + return true; +#else + NS_RUNTIMEABORT("ContentsScaleFactorChanged is an OSX-only message"); + return false; +#endif +} + #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) // Create a new window from NPWindow bool PluginInstanceChild::CreateWindow(const NPRemoteWindow& aWindow) @@ -3957,7 +3975,9 @@ PluginInstanceChild::SwapSurfaces() (mDoubleBufferCARenderer.GetFrontSurfaceWidth() != mDoubleBufferCARenderer.GetBackSurfaceWidth() || mDoubleBufferCARenderer.GetFrontSurfaceHeight() != - mDoubleBufferCARenderer.GetBackSurfaceHeight())) { + mDoubleBufferCARenderer.GetBackSurfaceHeight() || + mDoubleBufferCARenderer.GetFrontSurfaceContentsScaleFactor() != + mDoubleBufferCARenderer.GetBackSurfaceContentsScaleFactor())) { mDoubleBufferCARenderer.ClearFrontSurface(); } diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInstanceChild.h index 108f8e6cfb1c..8c2a2dd4e08e 100644 --- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -126,6 +126,9 @@ protected: virtual bool RecvWindowPosChanged(const NPRemoteEvent& event) MOZ_OVERRIDE; + virtual bool + RecvContentsScaleFactorChanged(const double& aContentsScaleFactor) MOZ_OVERRIDE; + virtual bool AnswerNPP_Destroy(NPError* result); diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index 234273019dd8..caa8b8a126ed 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -799,7 +799,14 @@ PluginInstanceParent::IsRemoteDrawingCoreAnimation(bool *aDrawing) NPDrawingModelInvalidatingCoreAnimation == (NPDrawingModel)mDrawingModel); return NS_OK; } -#endif + +nsresult +PluginInstanceParent::ContentsScaleFactorChanged(double aContentsScaleFactor) +{ + bool rv = SendContentsScaleFactorChanged(aContentsScaleFactor); + return rv ? NS_OK : NS_ERROR_FAILURE; +} +#endif // #ifdef XP_MACOSX nsresult PluginInstanceParent::SetBackgroundUnknown() diff --git a/dom/plugins/ipc/PluginInstanceParent.h b/dom/plugins/ipc/PluginInstanceParent.h index 493b22268af6..571068f3bb1f 100644 --- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -271,6 +271,7 @@ public: nsresult GetImageSize(nsIntSize* aSize); #ifdef XP_MACOSX nsresult IsRemoteDrawingCoreAnimation(bool *aDrawing); + nsresult ContentsScaleFactorChanged(double aContentsScaleFactor); #endif nsresult SetBackgroundUnknown(); nsresult BeginUpdateBackground(const nsIntRect& aRect, diff --git a/dom/plugins/ipc/PluginLibrary.h b/dom/plugins/ipc/PluginLibrary.h index 1097be308953..1258431ea5d1 100644 --- a/dom/plugins/ipc/PluginLibrary.h +++ b/dom/plugins/ipc/PluginLibrary.h @@ -73,6 +73,7 @@ public: virtual bool IsOOP() = 0; #if defined(XP_MACOSX) virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) = 0; + virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) = 0; #endif /** diff --git a/dom/plugins/ipc/PluginModuleParent.cpp b/dom/plugins/ipc/PluginModuleParent.cpp index 8a95eb0e9069..24f0244914b7 100755 --- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -1185,7 +1185,17 @@ PluginModuleParent::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) return i->IsRemoteDrawingCoreAnimation(aDrawing); } -#endif + +nsresult +PluginModuleParent::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) +{ + PluginInstanceParent* i = InstCast(instance); + if (!i) + return NS_ERROR_FAILURE; + + return i->ContentsScaleFactorChanged(aContentsScaleFactor); +} +#endif // #if defined(XP_MACOSX) bool PluginModuleParent::AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable, diff --git a/dom/plugins/ipc/PluginModuleParent.h b/dom/plugins/ipc/PluginModuleParent.h index de419ebeb723..2005929d7bbc 100644 --- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -271,6 +271,7 @@ private: #if defined(XP_MACOSX) virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing); + virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor); #endif #if defined(MOZ_WIDGET_QT) && (MOZ_PLATFORM_MAEMO == 6) virtual nsresult HandleGUIEvent(NPP instance, const nsGUIEvent& anEvent, diff --git a/dom/plugins/ipc/PluginUtilsOSX.h b/dom/plugins/ipc/PluginUtilsOSX.h index be88f7bd4442..174ba2e63f37 100644 --- a/dom/plugins/ipc/PluginUtilsOSX.h +++ b/dom/plugins/ipc/PluginUtilsOSX.h @@ -50,12 +50,14 @@ public: // Returns height in "display pixels". Multiply by // mContentsScaleFactor to get device pixels. size_t GetFrontSurfaceHeight(); + double GetFrontSurfaceContentsScaleFactor(); // Returns width in "display pixels". Multiply by // mContentsScaleFactor to get device pixels. size_t GetBackSurfaceWidth(); // Returns height in "display pixels". Multiply by // mContentsScaleFactor to get device pixels. size_t GetBackSurfaceHeight(); + double GetBackSurfaceContentsScaleFactor(); IOSurfaceID GetFrontSurfaceID(); bool HasBackSurface(); diff --git a/dom/plugins/ipc/PluginUtilsOSX.mm b/dom/plugins/ipc/PluginUtilsOSX.mm index e33ecc5c82fd..44c5df51e4ef 100644 --- a/dom/plugins/ipc/PluginUtilsOSX.mm +++ b/dom/plugins/ipc/PluginUtilsOSX.mm @@ -269,6 +269,14 @@ size_t nsDoubleBufferCARenderer::GetFrontSurfaceHeight() { return mFrontSurface->GetHeight(); } +double nsDoubleBufferCARenderer::GetFrontSurfaceContentsScaleFactor() { + if (!HasFrontSurface()) { + return 1.0; + } + + return mFrontSurface->GetContentsScaleFactor(); +} + size_t nsDoubleBufferCARenderer::GetBackSurfaceWidth() { if (!HasBackSurface()) { return 0; @@ -285,6 +293,14 @@ size_t nsDoubleBufferCARenderer::GetBackSurfaceHeight() { return mBackSurface->GetHeight(); } +double nsDoubleBufferCARenderer::GetBackSurfaceContentsScaleFactor() { + if (!HasBackSurface()) { + return 1.0; + } + + return mBackSurface->GetContentsScaleFactor(); +} + IOSurfaceID nsDoubleBufferCARenderer::GetFrontSurfaceID() { if (!HasFrontSurface()) { return 0; diff --git a/gfx/2d/QuartzSupport.mm b/gfx/2d/QuartzSupport.mm index cc4319a428ae..f6ef9c1fb7e4 100644 --- a/gfx/2d/QuartzSupport.mm +++ b/gfx/2d/QuartzSupport.mm @@ -743,6 +743,21 @@ void nsCARenderer::SetBounds(int aWidth, int aHeight) { layer.contentsScale = mContentsScaleFactor; } } + } else { + // These settings are the default values. But they might have been + // changed as above if we were previously running in a HiDPI mode + // (i.e. if we just switched from that to a non-HiDPI mode). + [layer setAffineTransform:CGAffineTransformIdentity]; + if ([layer respondsToSelector:@selector(setContentsScale:)]) { +#if !defined(MAC_OS_X_VERSION_10_7) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + Class CGBridgeLayerClass = ::NSClassFromString(@"CGBridgeLayer"); + if (!CGBridgeLayerClass || ![layer isKindOfClass:CGBridgeLayerClass]) +#endif + { + layer.contentsScale = 1.0; + } + } } [CATransaction commit]; @@ -838,11 +853,19 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight, int renderer_width = caRenderer.bounds.size.width / intScaleFactor; int renderer_height = caRenderer.bounds.size.height / intScaleFactor; - if (renderer_width != aWidth || renderer_height != aHeight) { + if (renderer_width != aWidth || renderer_height != aHeight || + mContentsScaleFactor != aContentsScaleFactor) { // XXX: This should be optimized to not rescale the buffer // if we are resizing down. + // caLayer is the CALayer* provided by the plugin, so we need to preserve + // it across the call to Destroy(). CALayer* caLayer = [caRenderer layer]; + // mIOSurface is set by AttachIOSurface(), not by SetupRenderer(). So + // since it may have been set by a prior call to AttachIOSurface(), we + // need to preserve it across the call to Destroy(). + mozilla::RefPtr ioSurface = mIOSurface; Destroy(); + mIOSurface = ioSurface; if (SetupRenderer(caLayer, aWidth, aHeight, aContentsScaleFactor, mAllowOfflineRenderer) != NS_OK) { return NS_ERROR_FAILURE; diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 7126627b6998..b5417d2a6afe 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -2072,6 +2072,15 @@ nsObjectFrame::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() && NS_IS_PLUGIN_EVENT(anEvent)) { *anEventStatus = mInstanceOwner->ProcessEvent(*anEvent); diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index f163fda77482..fce825d8288d 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -751,7 +751,8 @@ nsresult nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsIView* aView, nsEven NS_IS_IME_RELATED_EVENT(aEvent) || NS_IS_NON_RETARGETED_PLUGIN_EVENT(aEvent) || aEvent->message == NS_PLUGIN_ACTIVATE || - aEvent->message == NS_PLUGIN_FOCUS)) { + aEvent->message == NS_PLUGIN_FOCUS || + aEvent->message == NS_PLUGIN_RESOLUTION_CHANGED)) { while (view && !view->GetFrame()) { view = view->GetParent(); } diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 2f2158a6dec3..f8c97fc301aa 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -778,13 +778,18 @@ nsChildView::BackingScaleFactorChanged() mBackingScaleFactor = newScale; - if (!mWidgetListener || mWidgetListener->GetXULWindow()) { - return; + if (mWidgetListener && !mWidgetListener->GetXULWindow()) { + nsIPresShell* presShell = mWidgetListener->GetPresShell(); + if (presShell) { + presShell->BackingScaleFactorChanged(); + } } - nsIPresShell* presShell = mWidgetListener->GetPresShell(); - if (presShell) { - presShell->BackingScaleFactorChanged(); + if (IsPluginView()) { + nsEventStatus status = nsEventStatus_eIgnore; + nsGUIEvent guiEvent(true, NS_PLUGIN_RESOLUTION_CHANGED, this); + guiEvent.time = PR_IntervalNow(); + DispatchEvent(&guiEvent, status); } } diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index ad09db94ffaf..772cfe241b6c 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -173,6 +173,11 @@ class nsHashKey; #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_MOUSE_MESSAGE_START 300 #define NS_MOUSE_MOVE (NS_MOUSE_MESSAGE_START) #define NS_MOUSE_BUTTON_UP (NS_MOUSE_MESSAGE_START + 1) @@ -1778,7 +1783,8 @@ inline bool NS_IsEventUsingCoordinates(nsEvent* aEvent) return !NS_IS_KEY_EVENT(aEvent) && !NS_IS_IME_RELATED_EVENT(aEvent) && !NS_IS_CONTEXT_MENU_KEY(aEvent) && !NS_IS_ACTIVATION_EVENT(aEvent) && !NS_IS_PLUGIN_EVENT(aEvent) && - !NS_IS_CONTENT_COMMAND_EVENT(aEvent); + !NS_IS_CONTENT_COMMAND_EVENT(aEvent) && + aEvent->message != NS_PLUGIN_RESOLUTION_CHANGED; } /**