author | James Willcox <jwillcox@mozilla.com> |
Wed, 06 Jun 2012 22:39:36 -0400 | |
changeset 96032 | 1d1aabb06e7c4bf79ad13c4d47ce83ff68896762 |
parent 96031 | d8243c3234fe3708ffed4ccf37381e61e8b8f4bc |
child 96033 | 596ebdcb918886af05f0d7e8a2319d5ecc67891e |
push id | 22869 |
push user | emorley@mozilla.com |
push date | Thu, 07 Jun 2012 09:35:19 +0000 |
treeherder | mozilla-central@3933384d8315 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | blassey |
bugs | 759747 |
milestone | 16.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -78,16 +78,17 @@ nsNPAPIPluginInstance::nsNPAPIPluginInst : mDrawingModel(kDefaultDrawingModel), #ifdef MOZ_WIDGET_ANDROID mSurface(nsnull), mANPDrawingModel(0), mOnScreen(true), mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary), mWakeLocked(false), + mFullScreen(false), #endif mRunning(NOT_STARTED), mWindowless(false), mTransparent(false), mCached(false), mUsesDOMForCursor(false), mInPluginInitCall(false), mPlugin(nsnull), @@ -755,20 +756,25 @@ void nsNPAPIPluginInstance::MemoryPressu SendLifecycleEvent(this, kFreeMemory_ANPLifecycleAction); } void nsNPAPIPluginInstance::NotifyFullScreen(bool aFullScreen) { PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::NotifyFullScreen this=%p\n",this)); - if (RUNNING != mRunning) + if (RUNNING != mRunning || mFullScreen == aFullScreen) return; - SendLifecycleEvent(this, aFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction); + mFullScreen = aFullScreen; + SendLifecycleEvent(this, mFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction); + + if (mFullScreen && mFullScreenOrientation != dom::eScreenOrientation_None) { + AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation); + } } void nsNPAPIPluginInstance::SetANPDrawingModel(PRUint32 aModel) { mANPDrawingModel = aModel; } void* nsNPAPIPluginInstance::GetJavaSurface() @@ -784,16 +790,37 @@ void* nsNPAPIPluginInstance::GetJavaSurf void nsNPAPIPluginInstance::PostEvent(void* event) { PluginEventRunnable *r = new PluginEventRunnable(this, (ANPEvent*)event); mPostedEvents.AppendElement(nsRefPtr<PluginEventRunnable>(r)); NS_DispatchToMainThread(r); } +void nsNPAPIPluginInstance::SetFullScreenOrientation(PRUint32 orientation) +{ + if (mFullScreenOrientation == orientation) + return; + + PRUint32 oldOrientation = mFullScreenOrientation; + mFullScreenOrientation = orientation; + + if (mFullScreen) { + // We're already fullscreen so immediately apply the orientation change + + if (mFullScreenOrientation != dom::eScreenOrientation_None) { + AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation); + } else if (oldOrientation != dom::eScreenOrientation_None) { + // We applied an orientation when we entered fullscreen, but + // we don't want it anymore + AndroidBridge::Bridge()->UnlockScreenOrientation(); + } + } +} + void nsNPAPIPluginInstance::PopPostedEvent(PluginEventRunnable* r) { mPostedEvents.RemoveElement(r); } void nsNPAPIPluginInstance::SetWakeLock(bool aLocked) { if (aLocked == mWakeLocked)
--- a/dom/plugins/base/nsNPAPIPluginInstance.h +++ b/dom/plugins/base/nsNPAPIPluginInstance.h @@ -134,17 +134,17 @@ public: void* GetJavaSurface(); void PostEvent(void* event); // These are really mozilla::dom::ScreenOrientation, but it's // difficult to include that here PRUint32 FullScreenOrientation() { return mFullScreenOrientation; } - void SetFullScreenOrientation(PRUint32 orientation) { mFullScreenOrientation = orientation; } + void SetFullScreenOrientation(PRUint32 orientation); void SetWakeLock(bool aLock); #endif nsresult NewStreamListener(const char* aURL, void* notifyData, nsNPAPIPluginStreamListener** listener); nsNPAPIPluginInstance(); @@ -224,16 +224,17 @@ protected: friend class PluginEventRunnable; nsTArray<nsCOMPtr<PluginEventRunnable>> mPostedEvents; void PopPostedEvent(PluginEventRunnable* r); PRUint32 mFullScreenOrientation; bool mWakeLocked; + bool mFullScreen; #endif enum { NOT_STARTED, RUNNING, DESTROYING, DESTROYED } mRunning;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1738,17 +1738,17 @@ bool nsPluginInstanceOwner::AddPluginVie if (!mJavaView) return false; mJavaView = (void*)AndroidBridge::GetJNIEnv()->NewGlobalRef((jobject)mJavaView); } if (AndroidBridge::Bridge()) - AndroidBridge::Bridge()->AddPluginView((jobject)mJavaView, aRect, mFullScreen, mInstance->FullScreenOrientation()); + AndroidBridge::Bridge()->AddPluginView((jobject)mJavaView, aRect, mFullScreen); if (mFullScreen) sFullScreenInstance = this; return true; } void nsPluginInstanceOwner::RemovePluginView()
--- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -106,16 +106,17 @@ abstract public class GeckoApp public Favicons mFavicons; private static LayerController mLayerController; private static GeckoLayerClient mLayerClient; private AboutHomeContent mAboutHomeContent; private static AbsoluteLayout mPluginContainer; private static FindInPageBar mFindInPageBar; + private FullScreenHolder mFullScreenPluginContainer; private View mFullScreenPluginView; private HashMap<String, PowerManager.WakeLock> mWakeLocks = new HashMap<String, PowerManager.WakeLock>(); private int mRestoreMode = GeckoAppShell.RESTORE_NONE; private boolean mInitialized = false; static Vector<MenuItem> sAddonMenuItems = new Vector<MenuItem>(); @@ -1553,45 +1554,52 @@ abstract public class GeckoApp } void handleWindowClose(final int tabId) { Tabs tabs = Tabs.getInstance(); Tab tab = tabs.getTab(tabId); tabs.closeTab(tab); } - private void addFullScreenPluginView(View view, int orientation) { + private void addFullScreenPluginView(View view) { if (mFullScreenPluginView != null) { Log.w(LOGTAG, "Already have a fullscreen plugin view"); return; } setFullScreen(true); - mBrowserToolbar.hide(); - - if (orientation != GeckoScreenOrientationListener.eScreenOrientation_None) - GeckoScreenOrientationListener.getInstance().lockScreenOrientation(orientation); view.setWillNotDraw(false); if (view instanceof SurfaceView) { ((SurfaceView) view).setZOrderOnTop(true); } - mPluginContainer.addView(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + mFullScreenPluginContainer = new FullScreenHolder(this); + + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, + Gravity.CENTER); + mFullScreenPluginContainer.addView(view, layoutParams); + + + FrameLayout decor = (FrameLayout)getWindow().getDecorView(); + decor.addView(mFullScreenPluginContainer, layoutParams); + mFullScreenPluginView = view; } - void addPluginView(final View view, final Rect rect, final boolean isFullScreen, final int orientation) { + void addPluginView(final View view, final Rect rect, final boolean isFullScreen) { mMainHandler.post(new Runnable() { public void run() { Tabs tabs = Tabs.getInstance(); Tab tab = tabs.getSelectedTab(); if (isFullScreen) { - addFullScreenPluginView(view, orientation); + addFullScreenPluginView(view); return; } PluginLayer layer = (PluginLayer) tab.getPluginLayer(view); if (layer == null) { layer = new PluginLayer(view, rect, mLayerController.getView().getRenderer().getMaxTextureSize()); tab.addPluginLayer(view, layer); } else { @@ -1612,23 +1620,33 @@ abstract public class GeckoApp if (mFullScreenPluginView != view) { Log.w(LOGTAG, "Passed view is not the current full screen view"); return; } GeckoAppShell.onFullScreenPluginHidden(view); + mFullScreenPluginContainer.removeView(mFullScreenPluginView); + + // We need do do this on the next iteration in order to avoid + // a deadlock, see comment below in FullScreenHolder + mMainHandler.post(new Runnable() { + public void run() { + mLayerController.getView().setVisibility(View.VISIBLE); + } + }); + + FrameLayout decor = (FrameLayout)getWindow().getDecorView(); + decor.removeView(mFullScreenPluginContainer); + + mFullScreenPluginView = null; + GeckoScreenOrientationListener.getInstance().unlockScreenOrientation(); - setFullScreen(false); - mBrowserToolbar.show(); - - mPluginContainer.removeView(view); - mFullScreenPluginView = null; } void removePluginView(final View view, final boolean isFullScreen) { mMainHandler.post(new Runnable() { public void run() { Tabs tabs = Tabs.getInstance(); Tab tab = tabs.getSelectedTab(); @@ -3141,9 +3159,72 @@ abstract public class GeckoApp return true; } }); } public boolean linkerExtract() { return false; } + + private class FullScreenHolder extends FrameLayout { + + public FullScreenHolder(Context ctx) { + super(ctx); + } + + @Override + public void addView(View view, int index) { + /** + * This normally gets called when Flash adds a separate SurfaceView + * for the video. It is unhappy if we have the LayerView underneath + * it for some reason so we need to hide that. Hiding the LayerView causes + * its surface to be destroyed, which causes a pause composition + * event to be sent to Gecko. We synchronously wait for that to be + * processed. Simultaneously, however, Flash is waiting on a mutex so + * the post() below is an attempt to avoid a deadlock. + */ + super.addView(view, index); + + mMainHandler.post(new Runnable() { + public void run() { + mLayerController.getView().setVisibility(View.INVISIBLE); + } + }); + } + + /** + * The methods below are simply copied from what Android WebKit does. + * It wasn't ever called in my testing, but might as well + * keep it in case it is for some reason. The methods + * all return true because we don't want any events + * leaking out from the fullscreen view. + */ + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (event.isSystem()) { + return super.onKeyDown(keyCode, event); + } + mFullScreenPluginView.onKeyDown(keyCode, event); + return true; + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + if (event.isSystem()) { + return super.onKeyUp(keyCode, event); + } + mFullScreenPluginView.onKeyUp(keyCode, event); + return true; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return true; + } + + @Override + public boolean onTrackballEvent(MotionEvent event) { + mFullScreenPluginView.onTrackballEvent(event); + return true; + } + } }
--- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -1542,23 +1542,23 @@ public class GeckoAppShell catch (Exception e) { return true; } } public static void addPluginView(View view, int x, int y, int w, int h, - boolean isFullScreen, int orientation) + boolean isFullScreen) { ImmutableViewportMetrics pluginViewport; - Log.i(LOGTAG, "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + "fullscreen: " + isFullScreen + " orientation: " + orientation); + Log.i(LOGTAG, "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h + " fullscreen: " + isFullScreen); - GeckoApp.mAppContext.addPluginView(view, new Rect(x, y, x + w, y + h), isFullScreen, orientation); + GeckoApp.mAppContext.addPluginView(view, new Rect(x, y, x + w, y + h), isFullScreen); } public static void removePluginView(View view, boolean isFullScreen) { Log.i(LOGTAG, "removePluginView:" + view + " fullscreen: " + isFullScreen); GeckoApp.mAppContext.removePluginView(view, isFullScreen); } public static Surface createSurface() {
--- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -183,17 +183,17 @@ AndroidBridge::Init(JNIEnv *jEnv, else /* not Froyo */ jSurfacePointerField = jEnv->GetFieldID(jSurfaceClass, "mNativeSurface", "I"); jNotifyWakeLockChanged = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyWakeLockChanged", "(Ljava/lang/String;Ljava/lang/String;)V"); #ifdef MOZ_JAVA_COMPOSITOR jPumpMessageLoop = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "pumpMessageLoop", "()V"); - jAddPluginView = jEnv->GetStaticMethodID(jGeckoAppShellClass, "addPluginView", "(Landroid/view/View;IIIIZI)V"); + jAddPluginView = jEnv->GetStaticMethodID(jGeckoAppShellClass, "addPluginView", "(Landroid/view/View;IIIIZ)V"); jRemovePluginView = jEnv->GetStaticMethodID(jGeckoAppShellClass, "removePluginView", "(Landroid/view/View;Z)V"); jCreateSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "createSurface", "()Landroid/view/Surface;"); jShowSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "showSurface", "(Landroid/view/Surface;IIIIZZ)V"); jHideSurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideSurface", "(Landroid/view/Surface;)V"); jDestroySurface = jEnv->GetStaticMethodID(jGeckoAppShellClass, "destroySurface", "(Landroid/view/Surface;)V"); jLayerView = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("org/mozilla/gecko/gfx/LayerView")); @@ -2328,28 +2328,28 @@ NS_IMETHODIMP nsAndroidBridge::GetBrowse NS_IMETHODIMP nsAndroidBridge::SetBrowserApp(nsIAndroidBrowserApp *aBrowserApp) { if (nsAppShell::gAppShell) nsAppShell::gAppShell->SetBrowserApp(aBrowserApp); return NS_OK; } void -AndroidBridge::AddPluginView(jobject view, const gfxRect& rect, bool isFullScreen, int orientation) { +AndroidBridge::AddPluginView(jobject view, const gfxRect& rect, bool isFullScreen) { JNIEnv *env = GetJNIEnv(); if (!env) return; AutoLocalJNIFrame jniFrame(env); #if MOZ_JAVA_COMPOSITOR env->CallStaticVoidMethod(sBridge->mGeckoAppShellClass, sBridge->jAddPluginView, view, (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height, - isFullScreen, orientation); + isFullScreen); #else env->CallStaticVoidMethod(sBridge->mGeckoAppShellClass, sBridge->jAddPluginView, view, rect.x, rect.y, rect.width, rect.height); #endif } void
--- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -335,17 +335,17 @@ public: void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated, nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY); jobject CreateSurface(); void DestroySurface(jobject surface); void ShowSurface(jobject surface, const gfxRect& aRect, bool aInverted, bool aBlend); void HideSurface(jobject surface); - void AddPluginView(jobject view, const gfxRect& rect, bool isFullScreen, int orientation); + void AddPluginView(jobject view, const gfxRect& rect, bool isFullScreen); void RemovePluginView(jobject view, bool isFullScreen); // These methods don't use a ScreenOrientation because it's an // enum and that would require including the header which requires // include IPC headers which requires including basictypes.h which // requires a lot of changes... uint32_t GetScreenOrientation(); void EnableScreenOrientationNotifications();