Bug 602962 - Undo close tab thumbnail disappears when rotating screen orientation [r=smaug r=roc a=blocking-fennecb3]
authorVivien Nicolas <21@vingtetun.org>
Wed, 17 Nov 2010 08:46:00 -0500
changeset 57661 2cd50afa5a00164d43cbabc7d7bd1e843cbaf2ed
parent 57660 6cfd43067a07e1e7d818c02b6a7b1ea62e8ace02
child 57662 dc021bc9929f6a93abc1aac7867600d90c3ba2cc
push idunknown
push userunknown
push dateunknown
reviewerssmaug, roc, blocking-fennecb3
bugs602962
milestone2.0b8pre
Bug 602962 - Undo close tab thumbnail disappears when rotating screen orientation [r=smaug r=roc a=blocking-fennecb3]
content/base/src/nsContentUtils.cpp
content/base/src/nsGkAtomList.h
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/events/test/Makefile.in
content/events/test/bug602962.xul
content/events/test/test_bug602962.xul
layout/base/nsPresShell.cpp
widget/public/nsGUIEvent.h
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -587,16 +587,17 @@ nsContentUtils::InitializeEventTable() {
     { nsGkAtoms::onDOMFocusOut,                 NS_UI_FOCUSOUT, EventNameType_HTMLXUL, NS_UI_EVENT },
     { nsGkAtoms::oninput,                       NS_FORM_INPUT, EventNameType_HTMLXUL, NS_UI_EVENT },
                                                 
     { nsGkAtoms::onDOMMouseScroll,              NS_MOUSE_SCROLL, EventNameType_HTMLXUL, NS_MOUSE_SCROLL_EVENT },
     { nsGkAtoms::onMozMousePixelScroll,         NS_MOUSE_PIXEL_SCROLL, EventNameType_HTMLXUL, NS_MOUSE_SCROLL_EVENT },
                                                 
     { nsGkAtoms::onpageshow,                    NS_PAGE_SHOW, EventNameType_HTML, NS_EVENT },
     { nsGkAtoms::onpagehide,                    NS_PAGE_HIDE, EventNameType_HTML, NS_EVENT },
+    { nsGkAtoms::onMozBeforeResize,             NS_BEFORERESIZE_EVENT, EventNameType_None, NS_EVENT },
     { nsGkAtoms::onresize,                      NS_RESIZE_EVENT,
                                                 (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT },
     { nsGkAtoms::onscroll,                      NS_SCROLL_EVENT,
                                                 (EventNameType_HTMLXUL | EventNameType_SVGSVG), NS_EVENT_NULL },
     { nsGkAtoms::oncopy,                        NS_COPY, EventNameType_HTMLXUL, NS_EVENT },
     { nsGkAtoms::oncut,                         NS_CUT, EventNameType_HTMLXUL, NS_EVENT },
     { nsGkAtoms::onpaste,                       NS_PASTE, EventNameType_HTMLXUL, NS_EVENT },
     // XUL specific events
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -704,16 +704,17 @@ GK_ATOM(onpaint, "onpaint")
 GK_ATOM(onpaste, "onpaste")
 GK_ATOM(onpopuphidden, "onpopuphidden")
 GK_ATOM(onpopuphiding, "onpopuphiding")
 GK_ATOM(onpopupshowing, "onpopupshowing")
 GK_ATOM(onpopupshown, "onpopupshown")
 GK_ATOM(onreadystatechange, "onreadystatechange")
 GK_ATOM(onRequest, "onRequest")
 GK_ATOM(onreset, "onreset")
+GK_ATOM(onMozBeforeResize, "onMozBeforeResize")
 GK_ATOM(onresize, "onresize")
 GK_ATOM(onscroll, "onscroll")
 GK_ATOM(onselect, "onselect")
 GK_ATOM(onset, "onset")
 GK_ATOM(onsubmit, "onsubmit")
 GK_ATOM(ontext, "ontext")
 GK_ATOM(ontransitionend, "ontransitionend")
 GK_ATOM(onunderflow, "onunderflow")
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -88,16 +88,17 @@ static const char* const sEventNames[] =
 #ifdef MOZ_MEDIA
   "loadstart", "progress", "suspend", "emptied", "stalled", "play", "pause",
   "loadedmetadata", "loadeddata", "waiting", "playing", "canplay",
   "canplaythrough", "seeking", "seeked", "timeupdate", "ended", "ratechange",
   "durationchange", "volumechange", "MozAudioAvailable",
 #endif // MOZ_MEDIA
   "MozAfterPaint",
   "MozBeforePaint",
+  "MozBeforeResize",
   "MozSwipeGesture",
   "MozMagnifyGestureStart",
   "MozMagnifyGestureUpdate",
   "MozMagnifyGesture",
   "MozRotateGestureStart",
   "MozRotateGestureUpdate",
   "MozRotateGesture",
   "MozTapGesture",
@@ -1311,16 +1312,18 @@ const char* nsDOMEvent::GetEventName(PRU
     return sEventNames[eDOMEvents_volumechange];
   case NS_MOZAUDIOAVAILABLE:
     return sEventNames[eDOMEvents_mozaudioavailable];
 #endif
   case NS_AFTERPAINT:
     return sEventNames[eDOMEvents_afterpaint];
   case NS_BEFOREPAINT:
     return sEventNames[eDOMEvents_beforepaint];
+  case NS_BEFORERESIZE_EVENT:
+    return sEventNames[eDOMEvents_beforeresize];
   case NS_SIMPLE_GESTURE_SWIPE:
     return sEventNames[eDOMEvents_MozSwipeGesture];
   case NS_SIMPLE_GESTURE_MAGNIFY_START:
     return sEventNames[eDOMEvents_MozMagnifyGestureStart];
   case NS_SIMPLE_GESTURE_MAGNIFY_UPDATE:
     return sEventNames[eDOMEvents_MozMagnifyGestureUpdate];
   case NS_SIMPLE_GESTURE_MAGNIFY:
     return sEventNames[eDOMEvents_MozMagnifyGesture];
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -170,16 +170,17 @@ public:
     eDOMEvents_ended,
     eDOMEvents_ratechange,
     eDOMEvents_durationchange,
     eDOMEvents_volumechange,
     eDOMEvents_mozaudioavailable,
 #endif
     eDOMEvents_afterpaint,
     eDOMEvents_beforepaint,
+    eDOMEvents_beforeresize,
     eDOMEvents_MozSwipeGesture,
     eDOMEvents_MozMagnifyGestureStart,
     eDOMEvents_MozMagnifyGestureUpdate,
     eDOMEvents_MozMagnifyGesture,
     eDOMEvents_MozRotateGestureStart,
     eDOMEvents_MozRotateGestureUpdate,
     eDOMEvents_MozRotateGesture,
     eDOMEvents_MozTapGesture,
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -105,15 +105,17 @@ ifneq (mobile,$(MOZ_BUILD_APP))
 		test_dragstart.html \
 		$(NULL)
 endif
 
 _CHROME_FILES = \
 		test_bug415498.xul \
 		bug415498-doc1.html \
 		bug415498-doc2.html \
+		bug602962.xul \
+		test_bug602962.xul \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/events/test/bug602962.xul
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window onload="window.opener.doTest()" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <scrollbox id="page-scrollbox" style="border: 1px solid red; background-color: black;overflow: auto" flex="1">
+    <box id="page-box" style="border: 1px solid green;"/>
+  </scrollbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug602962.xul
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=602962
+-->
+<window title="Mozilla Bug 602962" onload="openWindow()"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <title>Test for Bug 602962</title>
+  <script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"/>
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+<body  xmlns="http://www.w3.org/1999/xhtml">
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=602962">Mozilla Bug 602962</a>
+  <p id="display"></p>
+<div id="content" style="display: none">
+</div>
+</body>
+
+<script class="testbody" type="application/javascript;version=1.8"><![CDATA[
+/** Test for Bug 602962 **/
+var scrollbox, sbo, content;
+var scrollX = 0, scrollY = 0;
+
+var mozBeforeResizeHasFired = false;
+var oldWidth = 0, oldHeight = 0;
+var win = null;
+
+function openWindow() {
+  win = window.open("chrome://mochitests/content/chrome/content/events/test/bug602962.xul", "_blank", "width=600,height=600");
+}
+
+function doTest() {
+  scrollbox = win.document.getElementById("page-scrollbox");
+  sbo = scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+  content = win.document.getElementById("page-box");
+  content.style.width = 400 + "px";
+  
+  win.addEventListener("resize", function() {
+    win.removeEventListener("resize", arguments.callee, false);
+
+    sbo.scrollBy(200, 0);
+    setTimeout(function() { resize(); }, 0);
+  }, false);
+
+  oldWidth = win.outerWidth;
+  oldHeight = win.outerHeight;
+  win.resizeTo(200, 400);
+}
+
+function resize() {
+  win.addEventListener("MozBeforeResize", function() {
+    win.removeEventListener("MozBeforeResize", arguments.callee, false);
+    mozBeforeResizeHasFired = true;
+
+    let x = {}, y = {};
+    sbo.getPosition(x, y);
+    scrollX = x.value, scrollY = y.value;
+    is(scrollX, 200, "Scroll X should not have changed yet");
+    is(scrollY, 0, "Scroll Y should not have changed yet");
+  }, false);
+
+  win.addEventListener("resize", function() {
+    content.style.width = (oldWidth + 400) + "px";
+    win.removeEventListener("resize", arguments.callee, true);
+    
+    setTimeout(function() {
+      finish();
+    }, 0);
+  }, true);
+
+  win.resizeTo(oldWidth, oldHeight);
+}
+
+function finish() {
+  is(mozBeforeResizeHasFired, true, "The MozBeforeResize event should already have fired");
+  sbo.scrollBy(scrollX, scrollY);
+
+  let x = {}, y = {};
+  sbo.getPosition(x, y);
+  is(x.value, 200, "Scroll X should have been restored to the value before the resize");
+  is(y.value, 0, "Scroll Y should have been restored to the value before the resize");
+
+  is(win.outerWidth, oldWidth, "Width should be resized");
+  is(win.outerHeight, oldHeight, "Height should be resized");
+  win.close();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+]]></script>
+
+</window>
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1350,16 +1350,17 @@ private:
   // Get the selected item and coordinates in device pixels relative to root
   // document's root view for element, first ensuring the element is onscreen
   void GetCurrentItemAndPositionForElement(nsIDOMElement *aCurrentEl,
                                            nsIContent **aTargetToUse,
                                            nsIntPoint& aTargetPt,
                                            nsIWidget *aRootWidget);
 
   void FireResizeEvent();
+  void FireBeforeResizeEvent();
   static void AsyncResizeEventCallback(nsITimer* aTimer, void* aPresShell);
   nsRevocableEventPtr<nsRunnableMethod<PresShell> > mResizeEvent;
   nsCOMPtr<nsITimer> mAsyncResizeEventTimer;
   PRPackedBool mAsyncResizeTimerIsActive;
   PRPackedBool mInResize;
 
 private:
 #ifdef DEBUG
@@ -2825,16 +2826,21 @@ PresShell::ResizeReflowIgnoreOverride(ns
   nsIFrame* rootFrame = FrameManager()->GetRootFrame();
 
   if (!rootFrame && aHeight == NS_UNCONSTRAINEDSIZE) {
     // We can't do the work needed for SizeToContent without a root
     // frame, and we want to return before setting the visible area.
     return NS_ERROR_NOT_AVAILABLE;
   }
 
+  if (!mIsDestroying && !mResizeEvent.IsPending() &&
+      !mAsyncResizeTimerIsActive) {
+    FireBeforeResizeEvent();
+  }
+
   mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
 
   // There isn't anything useful we can do if the initial reflow hasn't happened
   if (!rootFrame)
     return NS_OK;
 
   NS_ASSERTION(mViewManager, "Must have view manager");
   nsCOMPtr<nsIViewManager> viewManagerDeathGrip = mViewManager;
@@ -2901,16 +2907,32 @@ PresShell::ResizeReflowIgnoreOverride(ns
       }
     }
   }
 
   return NS_OK; //XXX this needs to be real. MMP
 }
 
 void
+PresShell::FireBeforeResizeEvent()
+{
+  if (mIsDocumentGone)
+    return;
+
+  // Send beforeresize event from here.
+  nsEvent event(PR_TRUE, NS_BEFORERESIZE_EVENT);
+
+  nsPIDOMWindow *window = mDocument->GetWindow();
+  if (window) {
+    nsCOMPtr<nsIPresShell> kungFuDeathGrip(this);
+    nsEventDispatcher::Dispatch(window, mPresContext, &event);
+  }
+}
+
+void
 PresShell::FireResizeEvent()
 {
   if (mAsyncResizeTimerIsActive) {
     mAsyncResizeTimerIsActive = PR_FALSE;
     mAsyncResizeEventTimer->Cancel();
   }
   mResizeEvent.Revoke();
 
--- a/widget/public/nsGUIEvent.h
+++ b/widget/public/nsGUIEvent.h
@@ -231,16 +231,19 @@ class nsHashKey;
 // the window is active. In the latter case, the dispatcher of the event
 // is expected to ensure that the plugin's widget is focused beforehand.
 #define NS_PLUGIN_ACTIVATE               (NS_WINDOW_START + 62)
 #define NS_PLUGIN_FOCUS                  (NS_WINDOW_START + 63)
 
 #define NS_OFFLINE                       (NS_WINDOW_START + 64)
 #define NS_ONLINE                        (NS_WINDOW_START + 65)
 
+// Indicates a resize will occur
+#define NS_BEFORERESIZE_EVENT            (NS_WINDOW_START + 66)
+
 #define NS_MOUSE_MESSAGE_START          300
 #define NS_MOUSE_MOVE                   (NS_MOUSE_MESSAGE_START)
 #define NS_MOUSE_BUTTON_UP              (NS_MOUSE_MESSAGE_START + 1)
 #define NS_MOUSE_BUTTON_DOWN            (NS_MOUSE_MESSAGE_START + 2)
 #define NS_MOUSE_ENTER                  (NS_MOUSE_MESSAGE_START + 22)
 #define NS_MOUSE_EXIT                   (NS_MOUSE_MESSAGE_START + 23)
 #define NS_MOUSE_DOUBLECLICK            (NS_MOUSE_MESSAGE_START + 24)
 #define NS_MOUSE_CLICK                  (NS_MOUSE_MESSAGE_START + 27)