Bug 798226, backout cd66c58db0f7 until the issue of the os adjusting the popup to fit onscreen can be solved.
authorNeil Deakin <neil@mozilla.com>
Mon, 24 Dec 2012 14:47:34 -0500
changeset 126106 c454966ef45c6258264dd1cf98c3fef2693a7051
parent 126105 671e04519d02a0f588a5456c5d372fbf8416f839
child 126107 d83930c9a712611baf5821468956fd752db55342
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs798226
milestone20.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 798226, backout cd66c58db0f7 until the issue of the os adjusting the popup to fit onscreen can be solved.
layout/xul/base/public/nsIPopupBoxObject.idl
layout/xul/base/src/nsMenuPopupFrame.cpp
layout/xul/base/src/nsMenuPopupFrame.h
layout/xul/base/src/nsPopupBoxObject.cpp
toolkit/content/tests/chrome/test_arrowpanel.xul
toolkit/content/widgets/popup.xml
--- a/layout/xul/base/public/nsIPopupBoxObject.idl
+++ b/layout/xul/base/public/nsIPopupBoxObject.idl
@@ -5,17 +5,17 @@
 
 #include "nsIBoxObject.idl"
 
 interface nsIDOMElement;
 interface nsIDOMNode;
 interface nsIDOMEvent;
 interface nsIDOMClientRect;
 
-[scriptable, uuid(DF60BA02-005B-4F61-AB1C-5632D0779DB4)]
+[scriptable, uuid(ACCEA57B-C3D8-4B6E-9101-90F04EE9DEA0)]
 interface nsIPopupBoxObject : nsISupports
 {
   /**
    *  This method is deprecated. Use openPopup or openPopupAtScreen instead.
    */
   void showPopup(in nsIDOMElement srcContent, in nsIDOMElement popupContent,
                  in long xpos, in long ypos,
                  in wstring popupType, in wstring anchorAlignment, 
@@ -161,20 +161,15 @@ interface nsIPopupBoxObject : nsISupport
    * Move an open popup to the given anchor position. The arguments have the same
    * meaning as the corresponding argument to openPopup. This method has no effect
    * on popups that are not open.
    */
   void moveToAnchor(in nsIDOMElement anchorElement,
                     in AString position,
                     in long x, in long y,
                     in boolean attributesOverride);
-
-  /** Returns the alignment position where the popup has appeared relative to its
-   *  anchor node or point, accounting for any flipping that occurred.
-   */
-  readonly attribute AString alignmentPosition;
 };
 
 %{C++
 nsresult
 NS_NewPopupBoxObject(nsIBoxObject** aResult);
 
 %}
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -77,17 +77,16 @@ nsMenuPopupFrame::nsMenuPopupFrame(nsIPr
   :nsBoxFrame(aShell, aContext),
   mCurrentMenu(nullptr),
   mPrefSize(-1, -1),
   mLastClientOffset(0, 0),
   mPopupType(ePopupTypePanel),
   mPopupState(ePopupClosed),
   mPopupAlignment(POPUPALIGNMENT_NONE),
   mPopupAnchor(POPUPALIGNMENT_NONE),
-  mPosition(POPUPPOSITION_UNKNOWN),
   mConsumeRollupEvent(nsIPopupBoxObject::ROLLUP_DEFAULT),
   mFlipBoth(false),
   mIsOpenChanged(false),
   mIsContextMenu(false),
   mAdjustOffsetForContextMenu(false),
   mGeneratedChildren(false),
   mMenuCanOverlapOSBar(false),
   mShouldAutoPosition(true),
@@ -530,18 +529,16 @@ nsMenuPopupFrame::InitPositionFromAnchor
   else if (aAlign.EqualsLiteral("topright"))
     mPopupAlignment = POPUPALIGNMENT_TOPRIGHT;
   else if (aAlign.EqualsLiteral("bottomleft"))
     mPopupAlignment = POPUPALIGNMENT_BOTTOMLEFT;
   else if (aAlign.EqualsLiteral("bottomright"))
     mPopupAlignment = POPUPALIGNMENT_BOTTOMRIGHT;
   else
     mPopupAlignment = POPUPALIGNMENT_NONE;
-
-  mPosition = POPUPPOSITION_UNKNOWN;
 }
 
 void
 nsMenuPopupFrame::InitializePopup(nsIContent* aAnchorContent,
                                   nsIContent* aTriggerContent,
                                   const nsAString& aPosition,
                                   int32_t aXPos, int32_t aYPos,
                                   bool aAttributesOverride)
@@ -549,17 +546,16 @@ nsMenuPopupFrame::InitializePopup(nsICon
   EnsureWidget();
 
   mPopupState = ePopupShowing;
   mAnchorContent = aAnchorContent;
   mTriggerContent = aTriggerContent;
   mXPos = aXPos;
   mYPos = aYPos;
   mAdjustOffsetForContextMenu = false;
-  mPosition = POPUPPOSITION_UNKNOWN;
 
   // if aAttributesOverride is true, then the popupanchor, popupalign and
   // position attributes on the <popup> override those values passed in.
   // If false, those attributes are only used if the values passed in are empty
   if (aAnchorContent) {
     nsAutoString anchor, align, position, flip;
     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::popupanchor, anchor);
     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::popupalign, align);
@@ -585,62 +581,52 @@ nsMenuPopupFrame::InitializePopup(nsICon
     // if there is a space in the position, assume it is the anchor and
     // alignment as two separate tokens.
     if (spaceIdx >= 0) {
       InitPositionFromAnchorAlign(Substring(position, 0, spaceIdx), Substring(position, spaceIdx + 1));
     }
     else if (position.EqualsLiteral("before_start")) {
       mPopupAnchor = POPUPALIGNMENT_TOPLEFT;
       mPopupAlignment = POPUPALIGNMENT_BOTTOMLEFT;
-      mPosition = POPUPPOSITION_BEFORESTART;
     }
     else if (position.EqualsLiteral("before_end")) {
       mPopupAnchor = POPUPALIGNMENT_TOPRIGHT;
       mPopupAlignment = POPUPALIGNMENT_BOTTOMRIGHT;
-      mPosition = POPUPPOSITION_BEFOREEND;
     }
     else if (position.EqualsLiteral("after_start")) {
       mPopupAnchor = POPUPALIGNMENT_BOTTOMLEFT;
       mPopupAlignment = POPUPALIGNMENT_TOPLEFT;
-      mPosition = POPUPPOSITION_AFTERSTART;
     }
     else if (position.EqualsLiteral("after_end")) {
       mPopupAnchor = POPUPALIGNMENT_BOTTOMRIGHT;
       mPopupAlignment = POPUPALIGNMENT_TOPRIGHT;
-      mPosition = POPUPPOSITION_AFTEREND;
     }
     else if (position.EqualsLiteral("start_before")) {
       mPopupAnchor = POPUPALIGNMENT_TOPLEFT;
       mPopupAlignment = POPUPALIGNMENT_TOPRIGHT;
-      mPosition = POPUPPOSITION_STARTBEFORE;
     }
     else if (position.EqualsLiteral("start_after")) {
       mPopupAnchor = POPUPALIGNMENT_BOTTOMLEFT;
       mPopupAlignment = POPUPALIGNMENT_BOTTOMRIGHT;
-      mPosition = POPUPPOSITION_STARTAFTER;
     }
     else if (position.EqualsLiteral("end_before")) {
       mPopupAnchor = POPUPALIGNMENT_TOPRIGHT;
       mPopupAlignment = POPUPALIGNMENT_TOPLEFT;
-      mPosition = POPUPPOSITION_ENDBEFORE;
     }
     else if (position.EqualsLiteral("end_after")) {
       mPopupAnchor = POPUPALIGNMENT_BOTTOMRIGHT;
       mPopupAlignment = POPUPALIGNMENT_BOTTOMLEFT;
-      mPosition = POPUPPOSITION_ENDAFTER;
     }
     else if (position.EqualsLiteral("overlap")) {
       mPopupAnchor = POPUPALIGNMENT_TOPLEFT;
       mPopupAlignment = POPUPALIGNMENT_TOPLEFT;
-      mPosition = POPUPPOSITION_OVERLAP;
     }
     else if (position.EqualsLiteral("after_pointer")) {
       mPopupAnchor = POPUPALIGNMENT_TOPLEFT;
       mPopupAlignment = POPUPALIGNMENT_TOPLEFT;
-      mPosition = POPUPPOSITION_AFTERPOINTER;
       // XXXndeakin this is supposed to anchor vertically after, but with the
       // horizontal position as the mouse pointer.
       mYPos += 21;
     }
     else {
       InitPositionFromAnchorAlign(anchor, align);
     }
   }
@@ -1917,61 +1903,16 @@ nsMenuPopupFrame::SetAutoPosition(bool a
 }
 
 void
 nsMenuPopupFrame::SetConsumeRollupEvent(uint32_t aConsumeMode)
 {
   mConsumeRollupEvent = aConsumeMode;
 }
 
-int8_t
-nsMenuPopupFrame::GetAlignmentPosition() const
-{
-  // The code below handles most cases of alignment, anchor and position values. Those that are
-  // not handled just return POPUPPOSITION_UNKNOWN.
-
-  if (mPosition == POPUPPOSITION_OVERLAP || mPosition == POPUPPOSITION_AFTERPOINTER)
-    return mPosition;
-
-  int8_t position = mPosition;
-
-  if (position == POPUPPOSITION_UNKNOWN) {
-    switch (mPopupAnchor) {
-      case POPUPALIGNMENT_BOTTOMCENTER:
-        position = mPopupAlignment == POPUPALIGNMENT_TOPRIGHT ?
-                     POPUPPOSITION_AFTEREND : POPUPPOSITION_AFTERSTART;
-        break;
-      case POPUPALIGNMENT_TOPCENTER:
-        position = mPopupAlignment == POPUPALIGNMENT_BOTTOMRIGHT ?
-                     POPUPPOSITION_BEFOREEND : POPUPPOSITION_BEFORESTART;
-        break;
-      case POPUPALIGNMENT_LEFTCENTER:
-        position = mPopupAlignment == POPUPALIGNMENT_BOTTOMRIGHT ?
-                     POPUPPOSITION_STARTAFTER : POPUPPOSITION_STARTBEFORE;
-        break;
-      case POPUPALIGNMENT_RIGHTCENTER:
-        position = mPopupAlignment == POPUPALIGNMENT_BOTTOMLEFT ?
-                     POPUPPOSITION_ENDAFTER : POPUPPOSITION_ENDBEFORE;
-        break;
-      default:
-        break;
-    }
-  }
-
-  if (mHFlip) {
-    position = POPUPPOSITION_HFLIP(position);
-  }
-
-  if (mVFlip) {
-    position = POPUPPOSITION_VFLIP(position);
-  }
-
-  return position;
-}
-
 /**
  * KEEP THIS IN SYNC WITH nsContainerFrame::CreateViewForFrame
  * as much as possible. Until we get rid of views finally...
  */
 nsresult
 nsMenuPopupFrame::CreatePopupView()
 {
   if (HasView()) {
--- a/layout/xul/base/src/nsMenuPopupFrame.h
+++ b/layout/xul/base/src/nsMenuPopupFrame.h
@@ -74,33 +74,16 @@ enum FlipStyle {
 #define POPUPALIGNMENT_BOTTOMLEFT 2
 #define POPUPALIGNMENT_BOTTOMRIGHT -2
 
 #define POPUPALIGNMENT_LEFTCENTER 16
 #define POPUPALIGNMENT_RIGHTCENTER -16
 #define POPUPALIGNMENT_TOPCENTER 17
 #define POPUPALIGNMENT_BOTTOMCENTER 18
 
-// The constants here are selected so that horizontally and vertically flipping
-// can be easily handled using the two flip macros below.
-#define POPUPPOSITION_UNKNOWN -1
-#define POPUPPOSITION_BEFORESTART 0
-#define POPUPPOSITION_BEFOREEND 1
-#define POPUPPOSITION_AFTERSTART 2
-#define POPUPPOSITION_AFTEREND 3
-#define POPUPPOSITION_STARTBEFORE 4
-#define POPUPPOSITION_ENDBEFORE 5
-#define POPUPPOSITION_STARTAFTER 6
-#define POPUPPOSITION_ENDAFTER 7
-#define POPUPPOSITION_OVERLAP 8
-#define POPUPPOSITION_AFTERPOINTER 9
-
-#define POPUPPOSITION_HFLIP(v) (v ^ 1)
-#define POPUPPOSITION_VFLIP(v) (v ^ 2)
-
 #define INC_TYP_INTERVAL  1000  // 1s. If the interval between two keypresses is shorter than this, 
                                 //   treat as a continue typing
 // XXX, kyle.yuan@sun.com, there are 4 definitions for the same purpose:
 //  nsMenuPopupFrame.h, nsListControlFrame.cpp, listbox.xml, tree.xml
 //  need to find a good place to put them together.
 //  if someone changes one, please also change the other.
 
 #define CONTEXT_MENU_OFFSET_PIXELS 2
@@ -327,19 +310,16 @@ public:
   nsIntPoint ScreenPosition() const { return nsIntPoint(mScreenXPos, mScreenYPos); }
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists) MOZ_OVERRIDE;
 
   nsIntPoint GetLastClientOffset() const { return mLastClientOffset; }
 
-  // Return the alignment of the popup
-  int8_t GetAlignmentPosition() const;
-
 protected:
 
   // returns the popup's level.
   nsPopupLevel PopupLevel(bool aIsNoAutoHide) const;
 
   // redefine to tell the box system not to move the views.
   virtual void GetLayoutFlags(uint32_t& aFlags);
 
@@ -425,18 +405,16 @@ protected:
   nsIntPoint mLastClientOffset;
 
   nsPopupType mPopupType; // type of popup
   nsPopupState mPopupState; // open state of the popup
 
   // popup alignment relative to the anchor node
   int8_t mPopupAlignment;
   int8_t mPopupAnchor;
-  int8_t mPosition;
-
   // One of nsIPopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME
   int8_t mConsumeRollupEvent;
   bool mFlipBoth; // flip in both directions
 
   bool mIsOpenChanged; // true if the open state changed since the last layout
   bool mIsContextMenu; // true for context menus
   // true if we need to offset the popup to ensure it's not under the mouse
   bool mAdjustOffsetForContextMenu;
--- a/layout/xul/base/src/nsPopupBoxObject.cpp
+++ b/layout/xul/base/src/nsPopupBoxObject.cpp
@@ -302,66 +302,16 @@ nsPopupBoxObject::GetOuterScreenRect(nsI
       int32_t pp = menuPopupFrame->PresContext()->AppUnitsPerDevPixel();
       rect->SetLayoutRect(screenRect.ToAppUnits(pp));
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsPopupBoxObject::GetAlignmentPosition(nsAString& positionStr)
-{
-  positionStr.Truncate();
-
-  // This needs to flush layout.
-  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(true));
-  if (!menuPopupFrame)
-    return NS_OK;
-
-  int8_t position = menuPopupFrame->GetAlignmentPosition();
-  switch (position) {
-    case POPUPPOSITION_AFTERSTART:
-      positionStr.AssignLiteral("after_start");
-      break;
-    case POPUPPOSITION_AFTEREND:
-      positionStr.AssignLiteral("after_end");
-      break;
-    case POPUPPOSITION_BEFORESTART:
-      positionStr.AssignLiteral("before_start");
-      break;
-    case POPUPPOSITION_BEFOREEND:
-      positionStr.AssignLiteral("before_end");
-      break;
-    case POPUPPOSITION_STARTBEFORE:
-      positionStr.AssignLiteral("start_before");
-      break;
-    case POPUPPOSITION_ENDBEFORE:
-      positionStr.AssignLiteral("end_before");
-      break;
-    case POPUPPOSITION_STARTAFTER:
-      positionStr.AssignLiteral("start_after");
-      break;
-    case POPUPPOSITION_ENDAFTER:
-      positionStr.AssignLiteral("end_after");
-      break;
-    case POPUPPOSITION_OVERLAP:
-      positionStr.AssignLiteral("overlap");
-      break;
-    case POPUPPOSITION_AFTERPOINTER:
-      positionStr.AssignLiteral("after_pointer");
-      break;
-    default:
-      // Leave as an empty string.
-      break;
-  }
-
-  return NS_OK;
-}
-
 // Creation Routine ///////////////////////////////////////////////////////////////////////
 
 nsresult
 NS_NewPopupBoxObject(nsIBoxObject** aResult)
 {
   *aResult = new nsPopupBoxObject;
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
--- a/toolkit/content/tests/chrome/test_arrowpanel.xul
+++ b/toolkit/content/tests/chrome/test_arrowpanel.xul
@@ -20,156 +20,142 @@
   <iframe id="frame" type="content"
           src="data:text/html,&lt;input id='input'&gt;" width="100" height="100" left="225" top="120"/>
 </stack>
 
 <panel id="panel" type="arrow" onpopupshown="checkPanelPosition(this)" onpopuphidden="runNextTest.next()">
   <label id="panellabel" value="This is some text." height="65"/>
 </panel>
 
-<panel id="bigpanel" type="arrow" onpopupshown="checkBigPanel(this)" onpopuphidden="runNextTest.next()">
+<panel id="bigpanel" type="arrow" onpopupshown="checkBigPanel(this)" onpopuphidden="SimpleTest.finish()">
   <button label="This is some text." height="3000"/>
 </panel>
 
 <script type="application/javascript">
 <![CDATA[
 
 SimpleTest.waitForExplicitFinish();
 
 var expectedAnchor = null;
-var expectedSide = "", expectedAnchorEdge = "", expectedPack = "", expectedAlignment = "";
+var expectedSide = "", expectedAnchorEdge = "", expectedPack = "";
 var zoomFactor = 1;
 var runNextTest;
 
 function startTest()
 {
   runNextTest = nextTest();
   runNextTest.next();
 }
 
 function nextTest()
 {
   var panel = $("panel");
 
-  function openPopup(position, anchor, expected, anchorEdge, pack, alignment)
+  function openPopup(position, anchor, expected, anchorEdge, pack)
   {
     expectedAnchor = anchor instanceof Node ? anchor : $(anchor);
     expectedSide = expected;
     expectedAnchorEdge = anchorEdge;
     expectedPack = pack;
-    expectedAlignment = alignment == undefined ? position : alignment;
 
     panel.removeAttribute("side");
     panel.openPopup(expectedAnchor, position, 0, 0, false, false, null);
   }
 
-  for (var iter = 0; iter < 2; iter++) {
-    openPopup("after_start", "topleft", "top", "left", "start");
-    yield;
-    openPopup("after_start", "bottomleft", "bottom", "left", "start", "before_start");
-    yield;
-    openPopup("before_start", "topleft", "top", "left", "start", "after_start");
-    yield;
-    openPopup("before_start", "bottomleft", "bottom", "left", "start");
-    yield;
-    openPopup("after_start", "middle", "top", "left", "start");
-    yield;
-    openPopup("before_start", "middle", "bottom", "left", "start");
-    yield;
+  openPopup("after_start", "topleft", "top", "left", "start");
+  yield;
+  openPopup("after_start", "bottomleft", "bottom", "left", "start");
+  yield;
+  openPopup("before_start", "topleft", "top", "left", "start");
+  yield;
+  openPopup("before_start", "bottomleft", "bottom", "left", "start");
+  yield;
+  openPopup("after_start", "middle", "top", "left", "start");
+  yield;
+  openPopup("before_start", "middle", "bottom", "left", "start");
+  yield;
 
-    openPopup("after_start", "topright", "top", "right", "end", "after_end");
-    yield;
-    openPopup("after_start", "bottomright", "bottom", "right", "end", "before_end");
-    yield;
-    openPopup("before_start", "topright", "top", "right", "end", "after_end");
-    yield;
-    openPopup("before_start", "bottomright", "bottom", "right", "end", "before_end");
-    yield;
+  openPopup("after_start", "topright", "top", "right", "end");
+  yield;
+  openPopup("after_start", "bottomright", "bottom", "right", "end");
+  yield;
+  openPopup("before_start", "topright", "top", "right", "end");
+  yield;
+  openPopup("before_start", "bottomright", "bottom", "right", "end");
+  yield;
 
-    openPopup("after_end", "middle", "top", "right", "end");
-    yield;
-    openPopup("before_end", "middle", "bottom", "right", "end");
-    yield;
+  openPopup("after_end", "middle", "top", "right", "end");
+  yield;
+  openPopup("before_end", "middle", "bottom", "right", "end");
+  yield;
 
-    openPopup("start_before", "topleft", "left", "top", "start", "end_before");
-    yield;
-    openPopup("start_before", "topright", "right", "top", "start");
-    yield;
-    openPopup("end_before", "topleft", "left", "top", "start");
-    yield;
-    openPopup("end_before", "topright", "right", "top", "start", "start_before");
-    yield;
-    openPopup("start_before", "middle", "right", "top", "start");
-    yield;
-    openPopup("end_before", "middle", "left", "top", "start");
-    yield;
+  openPopup("start_before", "topleft", "left", "top", "start");
+  yield;
+  openPopup("start_before", "topright", "right", "top", "start");
+  yield;
+  openPopup("end_before", "topleft", "left", "top", "start");
+  yield;
+  openPopup("end_before", "topright", "right", "top", "start");
+  yield;
+  openPopup("start_before", "middle", "right", "top", "start");
+  yield;
+  openPopup("end_before", "middle", "left", "top", "start");
+  yield;
 
-    openPopup("start_before", "bottomleft", "left", "bottom", "end", "end_after");
-    yield;
-    openPopup("start_before", "bottomright", "right", "bottom", "end", "start_after");
-    yield;
-    openPopup("end_before", "bottomleft", "left", "bottom", "end", "end_after");
-    yield;
-    openPopup("end_before", "bottomright", "right", "bottom", "end", "start_after");
-    yield;
+  openPopup("start_before", "bottomleft", "left", "bottom", "end");
+  yield;
+  openPopup("start_before", "bottomright", "right", "bottom", "end");
+  yield;
+  openPopup("end_before", "bottomleft", "left", "bottom", "end");
+  yield;
+  openPopup("end_before", "bottomright", "right", "bottom", "end");
+  yield;
 
-    openPopup("start_after", "middle", "right", "bottom", "end");
-    yield;
-    openPopup("end_after", "middle", "left", "bottom", "end");
-    yield;
+  openPopup("start_after", "middle", "right", "bottom", "end");
+  yield;
+  openPopup("end_after", "middle", "left", "bottom", "end");
+  yield;
 
-    openPopup("topcenter bottomleft", "bottomleft", "bottom", "center left", "start", "before_start");
-    yield;
-    openPopup("bottomcenter topleft", "topleft", "top", "center left", "start", "after_start");
-    yield;
-    openPopup("topcenter bottomright", "bottomright", "bottom", "center right", "end", "before_end");
-    yield;
-    openPopup("bottomcenter topright", "topright", "top", "center right", "end", "after_end");
-    yield;
-    openPopup("topcenter bottomleft", "middle", "bottom", "center left", "start", "before_start");
-    yield;
-    openPopup("bottomcenter topleft", "middle", "top", "center left", "start", "after_start");
-    yield;
+  openPopup("topcenter bottomleft", "bottomleft", "bottom", "center left", "start");
+  yield;
+  openPopup("bottomcenter topleft", "topleft", "top", "center left", "start");
+  yield;
+  openPopup("topcenter bottomright", "bottomright", "bottom", "center right", "end");
+  yield;
+  openPopup("bottomcenter topright", "topright", "top", "center right", "end");
+  yield;
+  openPopup("topcenter bottomleft", "middle", "bottom", "center left", "start");
+  yield;
+  openPopup("bottomcenter topleft", "middle", "top", "center left", "start");
+  yield;
 
-    openPopup("leftcenter topright", "middle", "right", "center top", "start", "start_before");
-    yield;
-    openPopup("rightcenter bottomleft", "middle", "left", "center bottom", "end", "end_after");
-    yield;
+  openPopup("leftcenter topright", "middle", "right", "center top", "start");
+  yield;
+  openPopup("rightcenter bottomleft", "middle", "left", "center bottom", "end");
+  yield;
 
 /*
-    XXXndeakin disable these parts of the test which often cause problems, see bug 626563
+  XXXndeakin disable these parts of the test which often cause problems, see bug 626563
 
-    openPopup("after_start", frames[0].document.getElementById("input"), "top", "left", "start");
-    yield;
+  openPopup("after_start", frames[0].document.getElementById("input"), "top", "left", "start");
+  yield;
 
-    setScale(frames[0], 1.5);
-    openPopup("after_start", frames[0].document.getElementById("input"), "top", "left", "start");
-    yield;
+  setScale(frames[0], 1.5);
+  openPopup("after_start", frames[0].document.getElementById("input"), "top", "left", "start");
+  yield;
 
-    setScale(frames[0], 2.5);
-    openPopup("before_start", frames[0].document.getElementById("input"), "bottom", "left", "start");
-    yield;
+  setScale(frames[0], 2.5);
+  openPopup("before_start", frames[0].document.getElementById("input"), "bottom", "left", "start");
+  yield;
 
-    setScale(frames[0], 1);
+  setScale(frames[0], 1);
 */
 
-    $("bigpanel").openPopup($("topleft"), "after_start", 0, 0, false, false, null, "start");
-    yield;
-
-    // switch to rtl mode
-    document.documentElement.style.direction = "rtl";
-    $("topleft").setAttribute("right", "15");
-    $("topright").setAttribute("left", "15");
-    $("bottomleft").setAttribute("right", "15");
-    $("bottomright").setAttribute("left", "15");
-    $("topleft").removeAttribute("left");
-    $("topright").removeAttribute("right");
-    $("bottomleft").removeAttribute("left");
-    $("bottomright").removeAttribute("right");
-  }
+  $("bigpanel").openPopup($("topleft"), "after_start", 0, 0, false, false, null, "start");
+  yield;
 
   SimpleTest.finish();
   yield;
 }
 
 function setScale(win, scale)
 {
   var wn = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
@@ -185,25 +171,16 @@ function checkPanelPosition(panel)
   let anchor = panel.anchorNode;
   let adj = 0, hwinpos = 0, vwinpos = 0;
   if (anchor.ownerDocument != document) {
     var framerect = anchor.ownerDocument.defaultView.frameElement.getBoundingClientRect();
     hwinpos = framerect.left;
     vwinpos = framerect.top;
   }
 
-  // Positions are reversed in rtl yet the coordinates used in the computations
-  // are not, so flip the expected label side and anchor edge.
-  var isRTL = (window.getComputedStyle(panel).direction == "rtl");
-  if (isRTL) {
-    var flipLeftRight = function (val) val == "left" ? "right" : "left";
-    expectedAnchorEdge = expectedAnchorEdge.replace(/(left|right)/, flipLeftRight);
-    expectedSide = expectedSide.replace(/(left|right)/, flipLeftRight);
-  }
-
   var panelRect = panel.getBoundingClientRect();
   var anchorRect = anchor.getBoundingClientRect();
   var labelBO = $("panellabel").boxObject;
   var labelRect = { top: labelBO.y,
                     left: labelBO.x,
                     bottom: labelBO.y + labelBO.height,
                     right: labelBO.x + labelBO.width };
   switch (expectedSide) {
@@ -255,17 +232,16 @@ function checkPanelPosition(panel)
   }
 
   is(anchor, expectedAnchor, "anchor");
 
   var arrow = document.getAnonymousElementByAttribute(panel, "anonid", "arrow");
   is(arrow.getAttribute("side"), expectedSide, "panel arrow side");
   is(arrow.hidden, false, "panel hidden");
   is(arrow.parentNode.pack, expectedPack, "panel arrow pack");
-  is(panel.alignmentPosition, expectedAlignment, "panel alignmentPosition");
 
   panel.hidePopup();
 }
 
 function checkBigPanel(panel)
 {
   ok(panel.firstChild.getBoundingClientRect().height < 2800, "big panel height");
   panel.hidePopup();
--- a/toolkit/content/widgets/popup.xml
+++ b/toolkit/content/widgets/popup.xml
@@ -121,24 +121,16 @@
         ]]>
         </getter>
         <setter>
         <![CDATA[
           return this.popupBoxObject.autoPosition = val;
         ]]>
         </setter>
       </property>
-
-      <property name="alignmentPosition" readonly="true">
-        <getter>
-        <![CDATA[
-          return this.popupBoxObject.alignmentPosition;
-        ]]>
-        </getter>
-      </property>
       
       <method name="enableKeyboardNavigator">
         <parameter name="aEnableKeyboardNavigator"/>
         <body>
         <![CDATA[
           this.popupBoxObject.enableKeyboardNavigator(aEnableKeyboardNavigator);
         ]]>
         </body>
@@ -325,75 +317,152 @@
     </handlers>
   </binding>
 
   <binding id="arrowpanel" extends="chrome://global/content/bindings/popup.xml#panel">
     <content flip="both" side="top" position="bottomcenter topleft">
       <xul:box anonid="container" class="panel-arrowcontainer" flex="1"
                xbl:inherits="side,panelopen">
         <xul:box anonid="arrowbox" class="panel-arrowbox">
-          <xul:image anonid="arrow" class="panel-arrow" xbl:inherits="side"/>
+          <xul:image anonid="arrow" class="panel-arrow"/>
         </xul:box>
         <xul:box class="panel-arrowcontent" xbl:inherits="side,align,dir,orient,pack" flex="1">
           <children/>
           <xul:box class="panel-inner-arrowcontentfooter" xbl:inherits="footertype" hidden="true"/>
         </xul:box>
       </xul:box>
     </content>
     <implementation>
       <field name="_fadeTimer">null</field>
     </implementation>
     <handlers>
       <handler event="popupshowing" phase="target">
       <![CDATA[
+        var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
+        var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
         var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
 
         var anchor = this.anchorNode;
         if (!anchor) {
           arrow.hidden = true;
           return;
         }
 
-        var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
-        var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
+        // Returns whether the first float is smaller than the second float or
+        // equals to it in a range of epsilon.
+        function smallerTo(aFloat1, aFloat2, aEpsilon)
+        {
+          return aFloat1 <= (aFloat2 + aEpsilon);
+        }
+
+        let popupRect = this.getBoundingClientRect();
+        let popupLeft = window.mozInnerScreenX + popupRect.left;
+        let popupTop = window.mozInnerScreenY + popupRect.top;
+        let popupRight = popupLeft + popupRect.width;
+        let popupBottom = popupTop + popupRect.height;
+
+        let anchorRect = anchor.getBoundingClientRect();
+        let anchorLeft = anchor.ownerDocument.defaultView.mozInnerScreenX + anchorRect.left;
+        let anchorTop = anchor.ownerDocument.defaultView.mozInnerScreenY + anchorRect.top;
+        let anchorRight = anchorLeft + anchorRect.width;
+        let anchorBottom = anchorTop + anchorRect.height;
 
-        var position = this.alignmentPosition;
-        if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
-          container.orient = "";
-          arrowbox.orient = "vertical";
-          arrowbox.pack = (position.indexOf("_after") > 0) ? "end" : "start";
+        try {
+          let anchorWindow = anchor.ownerDocument.defaultView;
+          if (anchorWindow != window) {
+            let utils = anchorWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
+                                     getInterface(Components.interfaces.nsIDOMWindowUtils);
+            let spp = utils.screenPixelsPerCSSPixel;
+            anchorLeft *= spp;
+            anchorRight *= spp;
+            anchorTop *= spp;
+            anchorBottom *= spp;
+          }
+        } catch(ex) { }
 
-          // The assigned side stays the same regardless of direction.
-          var isRTL = (window.getComputedStyle(this).direction == "rtl");
+        const epsilon = 0.2;
+
+        var horizPos = smallerTo(popupRight, anchorLeft, epsilon) ? -1 : smallerTo(anchorRight, popupLeft, epsilon) ? 1 : 0;
+        var vertPos = smallerTo(popupBottom, anchorTop, epsilon) ? -1 : smallerTo(anchorBottom, popupTop, epsilon) ? 1 : 0;
 
-          if (position.indexOf("start_") == 0) {
-            container.dir = "reverse";
-            this.setAttribute("side", isRTL ? "left" : "right");
+        var anchorClass = "";
+        var hideAnchor = false;
+        if (horizPos == 0) {
+          container.orient = "vertical";
+          arrowbox.orient = "";
+          if (vertPos == 0) {
+            hideAnchor = true;
           }
           else {
-            container.dir = "";
-            this.setAttribute("side", isRTL ? "right" : "left");
+            let pack = "";
+
+            // We have to guess where to position the arrow given that we don't
+            // have access to the parameters passed to |openPopup|.
+
+            // If the popup is on the left of the anchor.
+            if (smallerTo(popupLeft, anchorLeft, epsilon) && smallerTo(popupRight, anchorRight, epsilon)) {
+              pack = "end";
+            // If the popup is on the right of the anchor.
+            } else if (smallerTo(anchorLeft, popupLeft, epsilon) && smallerTo(anchorRight, popupRight, epsilon)) {
+              pack = "start"; //(popupLeft + popupRect.width / 2 > anchorRight) ? "start" : "end";
+            // If the popup is not on the right nor on the left.
+            // Basically, that means one is above the other and one is bigger
+            // than the other.
+            // In that case, we can't easily choose a position for the arrow so
+            // we have to guess depending on which side the popup is more close to.
+            } else {
+              pack = (Math.abs(popupLeft - anchorLeft) < Math.abs(popupRight - anchorRight)) ? "start" : "end";
+            }
+
+            // In RTL, everything should be inverted.
+            if (window.getComputedStyle(this).direction == "rtl") {
+              pack = (pack == "start") ? "end" : "start";
+            }
+
+            arrowbox.pack = pack;
+
+            if (vertPos == 1) {
+              container.dir = "";
+              anchorClass = "top";
+            }
+            else if (vertPos == -1) {
+              container.dir = "reverse"; 
+              anchorClass = "bottom";
+            }
           }
         }
-        else if (position.indexOf("before_") == 0 || position.indexOf("after_") == 0) {
-          container.orient = "vertical";
-          arrowbox.orient = "";
-          arrowbox.pack = (position.indexOf("_end") > 0) ? "end" : "start";
-
-          if (position.indexOf("before_") == 0) {
-            container.dir = "reverse";
-            this.setAttribute("side", "bottom");
+        else if (vertPos == 0) {
+          container.orient = "";
+          arrowbox.orient = "vertical";
+          if (horizPos == 0) {
+            hideAnchor = true;
           }
           else {
-            container.dir = "";
-            this.setAttribute("side", "top");
+            let dir = "";
+            arrowbox.pack = popupTop + popupRect.height / 2 < anchorTop ? "end" : "start";
+            if (horizPos == 1) {
+              anchorClass = "left";
+            }
+            else if (horizPos == -1) {
+              dir = "reverse";
+              anchorClass = "right";
+            }
+            // In RTL, everything should be inverted.
+            if (window.getComputedStyle(this).direction == "rtl") {
+              dir = (dir == "") ? "reverse" : "";
+            }
+            container.dir = dir;
           }
         }
-
-        arrow.hidden = false;
+        else {
+          hideAnchor = true;
+        }
+        arrow.hidden = hideAnchor;
+        arrow.setAttribute("side", anchorClass);
+        this.setAttribute("side", anchorClass);
 
         // set fading
         var fade = this.getAttribute("fade");
         var fadeDelay = (fade == "fast") ? 1 : fade == "slow" ? 4000 : 0;
         if (fadeDelay) {
           this._fadeTimer = setTimeout(function (self) {
             self.style.opacity = 0.2;
           }, fadeDelay, this);