layout/xul/nsPopupBoxObject.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "nsCOMPtr.h"
     6 #include "nsIPopupBoxObject.h"
     7 #include "nsIRootBox.h"
     8 #include "nsBoxObject.h"
     9 #include "nsIPresShell.h"
    10 #include "nsFrameManager.h"
    11 #include "nsIContent.h"
    12 #include "nsIDOMElement.h"
    13 #include "nsNameSpaceManager.h"
    14 #include "nsGkAtoms.h"
    15 #include "nsMenuPopupFrame.h"
    16 #include "nsView.h"
    17 #include "mozilla/AppUnits.h"
    18 #include "mozilla/dom/DOMRect.h"
    20 using namespace mozilla::dom;
    22 class nsPopupBoxObject : public nsBoxObject,
    23                          public nsIPopupBoxObject
    24 {
    25 public:
    26   NS_DECL_ISUPPORTS_INHERITED
    27   NS_DECL_NSIPOPUPBOXOBJECT
    29   nsPopupBoxObject() {}
    30 protected:
    31   virtual ~nsPopupBoxObject() {}
    33   nsPopupSetFrame* GetPopupSetFrame();
    34 };
    36 NS_IMPL_ISUPPORTS_INHERITED(nsPopupBoxObject, nsBoxObject, nsIPopupBoxObject)
    38 nsPopupSetFrame*
    39 nsPopupBoxObject::GetPopupSetFrame()
    40 {
    41   nsIRootBox* rootBox = nsIRootBox::GetRootBox(GetPresShell(false));
    42   if (!rootBox)
    43     return nullptr;
    45   return rootBox->GetPopupSetFrame();
    46 }
    48 NS_IMETHODIMP
    49 nsPopupBoxObject::HidePopup()
    50 {
    51   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    52   if (pm && mContent)
    53     pm->HidePopup(mContent, false, true, false, false);
    55   return NS_OK;
    56 }
    58 NS_IMETHODIMP
    59 nsPopupBoxObject::ShowPopup(nsIDOMElement* aAnchorElement,
    60                             nsIDOMElement* aPopupElement,
    61                             int32_t aXPos, int32_t aYPos,
    62                             const char16_t *aPopupType,
    63                             const char16_t *aAnchorAlignment,
    64                             const char16_t *aPopupAlignment)
    65 {
    66   NS_ENSURE_TRUE(aPopupElement, NS_ERROR_INVALID_ARG);
    67   // srcContent can be null.
    69   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    70   if (pm && mContent) {
    71     nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
    72     nsAutoString popupType(aPopupType);
    73     nsAutoString anchor(aAnchorAlignment);
    74     nsAutoString align(aPopupAlignment);
    75     pm->ShowPopupWithAnchorAlign(mContent, anchorContent, anchor, align,
    76                                  aXPos, aYPos, popupType.EqualsLiteral("context"));
    77   }
    79   return NS_OK;
    80 }
    82 NS_IMETHODIMP
    83 nsPopupBoxObject::OpenPopup(nsIDOMElement* aAnchorElement,
    84                             const nsAString& aPosition,
    85                             int32_t aXPos, int32_t aYPos,
    86                             bool aIsContextMenu,
    87                             bool aAttributesOverride,
    88                             nsIDOMEvent* aTriggerEvent)
    89 {
    90   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
    91   if (pm && mContent) {
    92     nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
    93     pm->ShowPopup(mContent, anchorContent, aPosition, aXPos, aYPos,
    94                   aIsContextMenu, aAttributesOverride, false, aTriggerEvent);
    95   }
    97   return NS_OK;
    98 }
   100 NS_IMETHODIMP
   101 nsPopupBoxObject::OpenPopupAtScreen(int32_t aXPos, int32_t aYPos,
   102                                     bool aIsContextMenu,
   103                                     nsIDOMEvent* aTriggerEvent)
   104 {
   105   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   106   if (pm && mContent)
   107     pm->ShowPopupAtScreen(mContent, aXPos, aYPos, aIsContextMenu, aTriggerEvent);
   108   return NS_OK;
   109 }
   111 NS_IMETHODIMP
   112 nsPopupBoxObject::MoveTo(int32_t aLeft, int32_t aTop)
   113 {
   114   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   115   if (menuPopupFrame) {
   116     menuPopupFrame->MoveTo(aLeft, aTop, true);
   117   }
   119   return NS_OK;
   120 }
   122 NS_IMETHODIMP
   123 nsPopupBoxObject::MoveToAnchor(nsIDOMElement* aAnchorElement,
   124                                const nsAString& aPosition,
   125                                int32_t aXPos, int32_t aYPos,
   126                                bool aAttributesOverride)
   127 {
   128   if (mContent) {
   129     nsCOMPtr<nsIContent> anchorContent(do_QueryInterface(aAnchorElement));
   131     nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(mContent->GetPrimaryFrame());
   132     if (menuPopupFrame && menuPopupFrame->PopupState() == ePopupOpenAndVisible) {
   133       menuPopupFrame->MoveToAnchor(anchorContent, aPosition, aXPos, aYPos, aAttributesOverride);
   134     }
   135   }
   137   return NS_OK;
   138 }
   140 NS_IMETHODIMP
   141 nsPopupBoxObject::SizeTo(int32_t aWidth, int32_t aHeight)
   142 {
   143   if (!mContent)
   144     return NS_OK;
   146   nsAutoString width, height;
   147   width.AppendInt(aWidth);
   148   height.AppendInt(aHeight);
   150   nsCOMPtr<nsIContent> content = mContent;
   152   // We only want to pass aNotify=true to SetAttr once, but must make sure
   153   // we pass it when a value is being changed.  Thus, we check if the height
   154   // is the same and if so, pass true when setting the width.
   155   bool heightSame = content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::height, height, eCaseMatters);
   157   content->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, heightSame);
   158   content->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true);
   160   return NS_OK;
   161 }
   163 NS_IMETHODIMP
   164 nsPopupBoxObject::GetAutoPosition(bool* aShouldAutoPosition)
   165 {
   166   *aShouldAutoPosition = true;
   168   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   169   if (menuPopupFrame) {
   170     *aShouldAutoPosition = menuPopupFrame->GetAutoPosition();
   171   }
   173   return NS_OK;
   174 }
   176 NS_IMETHODIMP
   177 nsPopupBoxObject::SetAutoPosition(bool aShouldAutoPosition)
   178 {
   179   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   180   if (menuPopupFrame) {
   181     menuPopupFrame->SetAutoPosition(aShouldAutoPosition);
   182   }
   184   return NS_OK;
   185 }
   187 NS_IMETHODIMP
   188 nsPopupBoxObject::EnableRollup(bool aShouldRollup)
   189 {
   190   // this does nothing now
   191   return NS_OK;
   192 }
   194 NS_IMETHODIMP
   195 nsPopupBoxObject::SetConsumeRollupEvent(uint32_t aConsume)
   196 {
   197   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   198   if (menuPopupFrame) {
   199     menuPopupFrame->SetConsumeRollupEvent(aConsume);
   200   }
   202   return NS_OK;
   203 }
   205 NS_IMETHODIMP
   206 nsPopupBoxObject::EnableKeyboardNavigator(bool aEnableKeyboardNavigator)
   207 {
   208   if (!mContent)
   209     return NS_OK;
   211   // Use ignorekeys="true" on the popup instead of using this function.
   212   if (aEnableKeyboardNavigator)
   213     mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys, true);
   214   else
   215     mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::ignorekeys,
   216                       NS_LITERAL_STRING("true"), true);
   218   return NS_OK;
   219 }
   221 NS_IMETHODIMP
   222 nsPopupBoxObject::GetPopupState(nsAString& aState)
   223 {
   224   // set this here in case there's no frame for the popup
   225   aState.AssignLiteral("closed");
   227   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   228   if (menuPopupFrame) {
   229     switch (menuPopupFrame->PopupState()) {
   230       case ePopupShowing:
   231       case ePopupOpen:
   232         aState.AssignLiteral("showing");
   233         break;
   234       case ePopupOpenAndVisible:
   235         aState.AssignLiteral("open");
   236         break;
   237       case ePopupHiding:
   238       case ePopupInvisible:
   239         aState.AssignLiteral("hiding");
   240         break;
   241       case ePopupClosed:
   242         break;
   243       default:
   244         NS_NOTREACHED("Bad popup state");
   245         break;
   246     }
   247   }
   249   return NS_OK;
   250 }
   252 NS_IMETHODIMP
   253 nsPopupBoxObject::GetTriggerNode(nsIDOMNode** aTriggerNode)
   254 {
   255   *aTriggerNode = nullptr;
   257   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   258   nsIContent* triggerContent = nsMenuPopupFrame::GetTriggerContent(menuPopupFrame);
   259   if (triggerContent)
   260     CallQueryInterface(triggerContent, aTriggerNode);
   262   return NS_OK;
   263 }
   265 NS_IMETHODIMP
   266 nsPopupBoxObject::GetAnchorNode(nsIDOMElement** aAnchor)
   267 {
   268   *aAnchor = nullptr;
   270   nsMenuPopupFrame *menuPopupFrame = mContent ? do_QueryFrame(mContent->GetPrimaryFrame()) : nullptr;
   271   if (!menuPopupFrame)
   272     return NS_OK;
   274   nsIContent* anchor = menuPopupFrame->GetAnchor();
   275   if (anchor)
   276     CallQueryInterface(anchor, aAnchor);
   278   return NS_OK;
   279 }
   281 NS_IMETHODIMP
   282 nsPopupBoxObject::GetOuterScreenRect(nsIDOMClientRect** aRect)
   283 {
   284   DOMRect* rect = new DOMRect(mContent);
   286   NS_ADDREF(*aRect = rect);
   288   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   289   if (!menuPopupFrame)
   290     return NS_OK;
   292   // Return an empty rectangle if the popup is not open.
   293   nsPopupState state = menuPopupFrame->PopupState();
   294   if (state != ePopupOpen && state != ePopupOpenAndVisible)
   295     return NS_OK;
   297   nsView* view = menuPopupFrame->GetView();
   298   if (view) {
   299     nsIWidget* widget = view->GetWidget();
   300     if (widget) {
   301       nsIntRect screenRect;
   302       widget->GetScreenBounds(screenRect);
   304       int32_t pp = menuPopupFrame->PresContext()->AppUnitsPerDevPixel();
   305       rect->SetLayoutRect(screenRect.ToAppUnits(pp));
   306     }
   307   }
   309   return NS_OK;
   310 }
   312 NS_IMETHODIMP
   313 nsPopupBoxObject::GetAlignmentPosition(nsAString& positionStr)
   314 {
   315   positionStr.Truncate();
   317   // This needs to flush layout.
   318   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(true));
   319   if (!menuPopupFrame)
   320     return NS_OK;
   322   int8_t position = menuPopupFrame->GetAlignmentPosition();
   323   switch (position) {
   324     case POPUPPOSITION_AFTERSTART:
   325       positionStr.AssignLiteral("after_start");
   326       break;
   327     case POPUPPOSITION_AFTEREND:
   328       positionStr.AssignLiteral("after_end");
   329       break;
   330     case POPUPPOSITION_BEFORESTART:
   331       positionStr.AssignLiteral("before_start");
   332       break;
   333     case POPUPPOSITION_BEFOREEND:
   334       positionStr.AssignLiteral("before_end");
   335       break;
   336     case POPUPPOSITION_STARTBEFORE:
   337       positionStr.AssignLiteral("start_before");
   338       break;
   339     case POPUPPOSITION_ENDBEFORE:
   340       positionStr.AssignLiteral("end_before");
   341       break;
   342     case POPUPPOSITION_STARTAFTER:
   343       positionStr.AssignLiteral("start_after");
   344       break;
   345     case POPUPPOSITION_ENDAFTER:
   346       positionStr.AssignLiteral("end_after");
   347       break;
   348     case POPUPPOSITION_OVERLAP:
   349       positionStr.AssignLiteral("overlap");
   350       break;
   351     case POPUPPOSITION_AFTERPOINTER:
   352       positionStr.AssignLiteral("after_pointer");
   353       break;
   354     default:
   355       // Leave as an empty string.
   356       break;
   357   }
   359   return NS_OK;
   360 }
   362 NS_IMETHODIMP
   363 nsPopupBoxObject::GetAlignmentOffset(int32_t *aAlignmentOffset)
   364 {
   365   nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   366   if (!menuPopupFrame)
   367     return NS_OK;
   369   int32_t pp = mozilla::AppUnitsPerCSSPixel();
   370   // Note that the offset might be along either the X or Y axis, but for the
   371   // sake of simplicity we use a point with only the X axis set so we can
   372   // use ToNearestPixels().
   373   nsPoint appOffset(menuPopupFrame->GetAlignmentOffset(), 0);
   374   nsIntPoint popupOffset = appOffset.ToNearestPixels(pp);
   375   *aAlignmentOffset = popupOffset.x;
   376   return NS_OK;
   377 }
   379 // Creation Routine ///////////////////////////////////////////////////////////////////////
   381 nsresult
   382 NS_NewPopupBoxObject(nsIBoxObject** aResult)
   383 {
   384   *aResult = new nsPopupBoxObject;
   385   if (!*aResult)
   386     return NS_ERROR_OUT_OF_MEMORY;
   387   NS_ADDREF(*aResult);
   388   return NS_OK;
   389 }

mercurial