Bug 610834 - New windows opened don't get painted until resized. r=fabrice
authorJames Willcox <snorp@snorp.net>
Tue, 09 Aug 2011 12:08:19 -0400
changeset 76830 46b3d16fc427f98b441e734997dd6c649bb9f03c
parent 76829 73aafae10571356aa17af47e922f1af6118de217
child 76831 cd982d1f49d62bbc5a740475338e4cc31e1a1342
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs610834
milestone9.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
Bug 610834 - New windows opened don't get painted until resized. r=fabrice
mobile/chrome/content/browser.js
widget/src/android/AndroidJavaWrappers.cpp
widget/src/android/AndroidJavaWrappers.h
widget/src/android/nsAppShell.cpp
widget/src/android/nsAppShell.h
widget/src/android/nsWindow.cpp
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -382,22 +382,16 @@ var Browser = {
     messageManager.addMessageListener("Browser:CertException", this);
     messageManager.addMessageListener("Browser:BlockedSite", this);
     messageManager.addMessageListener("Browser:ErrorPage", this);
 
     // Broadcast a UIReady message so add-ons know we are finished with startup
     let event = document.createEvent("Events");
     event.initEvent("UIReady", true, false);
     window.dispatchEvent(event);
-
-    // If we have an opener this was not the first window opened and will not
-    // receive an initial resize event. instead we fire the resize handler manually
-    // Bug 610834
-    if (window.opener)
-      resizeHandler({ target: window });
   },
 
   _alertShown: function _alertShown() {
     // ensure that the full notification still visible, even if the urlbar is floating
     if (BrowserUI.isToolbarLocked())
       Browser.pageScrollboxScroller.scrollTo(0, 0);
   },
 
--- a/widget/src/android/AndroidJavaWrappers.cpp
+++ b/widget/src/android/AndroidJavaWrappers.cpp
@@ -453,16 +453,29 @@ AndroidGeckoEvent::Init(int aType)
 void
 AndroidGeckoEvent::Init(int x1, int y1, int x2, int y2)
 {
     mType = DRAW;
     mRect.SetEmpty();
 }
 
 void
+AndroidGeckoEvent::Init(AndroidGeckoEvent *aResizeEvent)
+{
+    NS_ASSERTION(aResizeEvent->Type() == SIZE_CHANGED, "Init called on non-SIZE_CHANGED event");
+
+    mType = FORCED_RESIZE;
+    mTime = aResizeEvent->mTime;
+    mP0.x = aResizeEvent->mP0.x;
+    mP0.y = aResizeEvent->mP0.y;
+    mP1.x = aResizeEvent->mP1.x;
+    mP1.y = aResizeEvent->mP1.y;
+}
+
+void
 AndroidGeckoSurfaceView::Init(jobject jobj)
 {
     NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
 
     wrapped_obj = jobj;
 }
 
 int
--- a/widget/src/android/AndroidJavaWrappers.h
+++ b/widget/src/android/AndroidJavaWrappers.h
@@ -381,20 +381,24 @@ public:
         Init(aType);
     }
     AndroidGeckoEvent(int x1, int y1, int x2, int y2) {
         Init(x1, y1, x2, y2);
     }
     AndroidGeckoEvent(JNIEnv *jenv, jobject jobj) {
         Init(jenv, jobj);
     }
+    AndroidGeckoEvent(AndroidGeckoEvent *aResizeEvent) {
+        Init(aResizeEvent);
+    }
 
     void Init(JNIEnv *jenv, jobject jobj);
     void Init(int aType);
     void Init(int x1, int y1, int x2, int y2);
+    void Init(AndroidGeckoEvent *aResizeEvent);
 
     int Action() { return mAction; }
     int Type() { return mType; }
     int64_t Time() { return mTime; }
     const nsIntPoint& P0() { return mP0; }
     const nsIntPoint& P1() { return mP1; }
     double Alpha() { return mAlpha; }
     double Beta() { return mBeta; }
@@ -482,16 +486,17 @@ public:
         SIZE_CHANGED = 8,
         ACTIVITY_STOPPING = 9,
         ACTIVITY_PAUSING = 10,
         ACTIVITY_SHUTDOWN = 11,
         LOAD_URI = 12,
         SURFACE_CREATED = 13,
         SURFACE_DESTROYED = 14,
         GECKO_EVENT_SYNC = 15,
+        FORCED_RESIZE = 16,
         dummy_java_enum_list_end
     };
 
     enum {
         IME_COMPOSITION_END = 0,
         IME_COMPOSITION_BEGIN = 1,
         IME_SET_TEXT = 2,
         IME_GET_TEXT = 3,
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -69,16 +69,17 @@
 using namespace mozilla;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *gWidgetLog = nsnull;
 #endif
 
 nsDeviceMotionSystem *gDeviceMotionSystem = nsnull;
 nsIGeolocationUpdate *gLocationCallback = nsnull;
+nsAutoPtr<mozilla::AndroidGeckoEvent> gLastSizeChange;
 
 nsAppShell *nsAppShell::gAppShell = nsnull;
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver)
 
 nsAppShell::nsAppShell()
     : mQueueLock("nsAppShell.mQueueLock"),
       mCondLock("nsAppShell.mCondLock"),
@@ -375,25 +376,41 @@ nsAppShell::ProcessNextNativeEvent(PRBoo
         };
         nsresult rv = cmdline->Init(3, const_cast<char **>(argv), nsnull, nsICommandLine::STATE_REMOTE_AUTO);
         if (NS_SUCCEEDED(rv))
             cmdline->Run();
         nsMemory::Free(uri);
         break;
     }
 
+    case AndroidGeckoEvent::SIZE_CHANGED: {
+        // store the last resize event to dispatch it to new windows with a FORCED_RESIZE event
+        if (curEvent != gLastSizeChange) {
+            gLastSizeChange = new AndroidGeckoEvent(curEvent);
+        }
+        nsWindow::OnGlobalAndroidEvent(curEvent);
+        break;
+    }
+
     default:
         nsWindow::OnGlobalAndroidEvent(curEvent);
     }
 
     EVLOG("nsAppShell: -- done event %p %d", (void*)curEvent.get(), curEvent->Type());
 
     return true;
 }
 
+void
+nsAppShell::ResendLastResizeEvent(nsWindow* aDest) {
+    if (gLastSizeChange) {
+        nsWindow::OnGlobalAndroidEvent(gLastSizeChange);
+    }
+}
+
 AndroidGeckoEvent*
 nsAppShell::GetNextEvent()
 {
     AndroidGeckoEvent *ae = nsnull;
     MutexAutoLock lock(mQueueLock);
     if (mEventQueue.Length()) {
         ae = mEventQueue[0];
         mEventQueue.RemoveElementAt(0);
--- a/widget/src/android/nsAppShell.h
+++ b/widget/src/android/nsAppShell.h
@@ -47,16 +47,18 @@
 #include "nsInterfaceHashtable.h"
 
 namespace mozilla {
 class AndroidGeckoEvent;
 bool ProcessNextEvent();
 void NotifyEvent();
 }
 
+class nsWindow;
+
 class nsAppShell :
     public nsBaseAppShell
 {
     typedef mozilla::CondVar CondVar;
     typedef mozilla::Mutex Mutex;
 
 public:
     static nsAppShell *gAppShell;
@@ -76,16 +78,17 @@ public:
     void PostEvent(mozilla::AndroidGeckoEvent *event);
     void RemoveNextEvent();
     void OnResume();
 
     nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver);
     void CallObserver(const nsAString &aObserverKey, const nsAString &aTopic, const nsAString &aData);
     void RemoveObserver(const nsAString &aObserverKey);
     void NotifyObservers(nsISupports *aSupports, const char *aTopic, const PRUnichar *aData);
+    void ResendLastResizeEvent(nsWindow* aDest);
 
 protected:
     virtual void ScheduleNativeEventCallback();
     virtual ~nsAppShell();
 
     Mutex mQueueLock;
     Mutex mCondLock;
     CondVar mQueueCond;
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -443,24 +443,16 @@ nsWindow::Resize(PRInt32 aX,
                  PRInt32 aWidth,
                  PRInt32 aHeight,
                  PRBool aRepaint)
 {
     ALOG("nsWindow[%p]::Resize [%d %d %d %d] (repaint %d)", (void*)this, aX, aY, aWidth, aHeight, aRepaint);
 
     PRBool needSizeDispatch = aWidth != mBounds.width || aHeight != mBounds.height;
 
-    if (IsTopLevel()) {
-        ALOG("... ignoring Resize sizes on toplevel window");
-        aX = 0;
-        aY = 0;
-        aWidth = gAndroidBounds.width;
-        aHeight = gAndroidBounds.height;
-    }
-
     mBounds.x = aX;
     mBounds.y = aY;
     mBounds.width = aWidth;
     mBounds.height = aHeight;
 
     if (needSizeDispatch)
         OnSizeChanged(gfxIntSize(aWidth, aHeight));
 
@@ -581,16 +573,18 @@ nsWindow::BringToFront()
     if (oldTop) {
         nsGUIEvent event(PR_TRUE, NS_DEACTIVATE, oldTop);
         DispatchEvent(&event);
     }
 
     nsGUIEvent event(PR_TRUE, NS_ACTIVATE, this);
     DispatchEvent(&event);
 
+    // force a window resize
+    nsAppShell::gAppShell->ResendLastResizeEvent(this);
     nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1));
 }
 
 NS_IMETHODIMP
 nsWindow::GetScreenBounds(nsIntRect &aRect)
 {
     nsIntPoint p = WidgetToScreenOffset();
 
@@ -734,21 +728,29 @@ nsWindow::OnGlobalAndroidEvent(AndroidGe
     if (!AndroidBridge::Bridge())
         return;
 
     nsWindow *win = TopWindow();
     if (!win)
         return;
 
     switch (ae->Type()) {
+        case AndroidGeckoEvent::FORCED_RESIZE:
+            win->mBounds.width = 0;
+            win->mBounds.height = 0;
+            // also resize the children
+            for (PRUint32 i = 0; i < win->mChildren.Length(); i++) {
+                win->mChildren[i]->mBounds.width = 0;
+                win->mChildren[i]->mBounds.height = 0;
+            }
         case AndroidGeckoEvent::SIZE_CHANGED: {
             int nw = ae->P0().x;
             int nh = ae->P0().y;
 
-            if (nw != gAndroidBounds.width ||
+            if (ae->Type() == AndroidGeckoEvent::FORCED_RESIZE || nw != gAndroidBounds.width ||
                 nh != gAndroidBounds.height) {
 
                 gAndroidBounds.width = nw;
                 gAndroidBounds.height = nh;
 
                 // tell all the windows about the new size
                 for (size_t i = 0; i < gTopLevelWindows.Length(); ++i) {
                     if (gTopLevelWindows[i]->mIsVisible)