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 75521 46b3d16fc427f98b441e734997dd6c649bb9f03c
parent 75520 73aafae10571356aa17af47e922f1af6118de217
child 75522 cd982d1f49d62bbc5a740475338e4cc31e1a1342
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersfabrice
bugs610834
milestone9.0a1
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)