зеркало из https://github.com/mozilla/gecko-dev.git
Bug 390589, capture not being released in some cases when popup is closed, fixes some focus issues, r+sr=bz,a=dbaron
This commit is contained in:
Родитель
fe1ef16802
Коммит
c0577cd8de
|
@ -561,6 +561,9 @@ protected:
|
|||
// get the nsMenuPopupFrame, if any, for the given content node
|
||||
nsMenuPopupFrame* GetPopupFrameForContent(nsIContent* aContent);
|
||||
|
||||
// return the topmost menu, skipping over invisible popups
|
||||
nsMenuChainItem* GetTopVisibleMenu();
|
||||
|
||||
// callbacks for ShowPopup and HidePopup as events may be done asynchronously
|
||||
void ShowPopupCallback(nsIContent* aPopup,
|
||||
nsMenuPopupFrame* aPopupFrame,
|
||||
|
|
|
@ -170,7 +170,8 @@ NS_IMETHODIMP nsXULPopupManager::ShouldRollupOnMouseWheelEvent(PRBool *aShouldRo
|
|||
{
|
||||
// should rollup only for autocomplete widgets
|
||||
// XXXndeakin this should really be something the popup has more control over
|
||||
*aShouldRollup = (mCurrentMenu && !mCurrentMenu->Frame()->IsMenu());
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
*aShouldRollup = (item && !item->Frame()->IsMenu());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -189,7 +190,7 @@ nsXULPopupManager::GetSubmenuWidgetChain(nsISupportsArray **_retval)
|
|||
// panels will roll up. If the click is inside a popup, they will not roll up
|
||||
nsresult rv = NS_NewISupportsArray(_retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsMenuChainItem* item = mCurrentMenu;
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
while (item) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
item->Frame()->GetWidget(getter_AddRefs(widget));
|
||||
|
@ -238,6 +239,15 @@ nsXULPopupManager::GetPopupFrameForContent(nsIContent* aContent)
|
|||
(GetFrameOfTypeForContent(aContent, nsGkAtoms::menuPopupFrame));
|
||||
}
|
||||
|
||||
nsMenuChainItem*
|
||||
nsXULPopupManager::GetTopVisibleMenu()
|
||||
{
|
||||
nsMenuChainItem* item = mCurrentMenu;
|
||||
while (item && item->Frame()->PopupState() == ePopupInvisible)
|
||||
item = item->GetParent();
|
||||
return item;
|
||||
}
|
||||
|
||||
void
|
||||
nsXULPopupManager::GetMouseLocation(nsIDOMNode** aNode, PRInt32* aOffset)
|
||||
{
|
||||
|
@ -676,7 +686,7 @@ nsXULPopupManager::HidePopupAfterDelay(nsMenuPopupFrame* aPopup)
|
|||
void
|
||||
nsXULPopupManager::HidePopupsInDocument(nsIDocument* aDocument)
|
||||
{
|
||||
nsMenuChainItem* item = mCurrentMenu;
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
while (item) {
|
||||
nsMenuChainItem* parent = item->GetParent();
|
||||
if (item->Content()->GetOwnerDoc() == aDocument) {
|
||||
|
@ -697,6 +707,8 @@ nsXULPopupManager::HidePopupsInDocument(nsIDocument* aDocument)
|
|||
}
|
||||
item = parent;
|
||||
}
|
||||
|
||||
SetCaptureState(nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -707,7 +719,7 @@ nsXULPopupManager::ExecuteMenu(nsIContent* aMenu, nsEvent* aEvent)
|
|||
// opens a modal dialog. The views associated with the popups needed to be
|
||||
// hidden and the accesibility events fired before the command executes, but
|
||||
// the popuphiding/popuphidden events are fired afterwards.
|
||||
nsMenuChainItem* item = mCurrentMenu;
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
while (item) {
|
||||
// if it isn't a <menupopup>, don't close it automatically
|
||||
if (!item->IsMenu())
|
||||
|
@ -718,6 +730,8 @@ nsXULPopupManager::ExecuteMenu(nsIContent* aMenu, nsEvent* aEvent)
|
|||
item = next;
|
||||
}
|
||||
|
||||
SetCaptureState(nsnull);
|
||||
|
||||
// Create a trusted event if the triggering event was trusted, or if
|
||||
// we're called from chrome code (since at least one of our caller
|
||||
// passes in a null event).
|
||||
|
@ -867,7 +881,7 @@ nsXULPopupManager::IsPopupOpen(nsIContent* aPopup)
|
|||
PRBool
|
||||
nsXULPopupManager::IsPopupOpenForMenuParent(nsIMenuParent* aMenuParent)
|
||||
{
|
||||
nsMenuChainItem* item = mCurrentMenu;
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
while (item) {
|
||||
nsMenuPopupFrame* popup = item->Frame();
|
||||
if (popup && popup->IsOpen()) {
|
||||
|
@ -891,7 +905,8 @@ nsXULPopupManager::GetOpenPopups()
|
|||
|
||||
nsMenuChainItem* item = mCurrentMenu;
|
||||
while (item) {
|
||||
popups.AppendElement(static_cast<nsIFrame*>(item->Frame()));
|
||||
if (item->Frame()->PopupState() != ePopupInvisible)
|
||||
popups.AppendElement(static_cast<nsIFrame*>(item->Frame()));
|
||||
item = item->GetParent();
|
||||
}
|
||||
|
||||
|
@ -1037,7 +1052,7 @@ nsXULPopupManager::PopupDestroyed(nsMenuPopupFrame* aPopup)
|
|||
PRBool
|
||||
nsXULPopupManager::HasContextMenu(nsMenuPopupFrame* aPopup)
|
||||
{
|
||||
nsMenuChainItem* item = mCurrentMenu;
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
while (item && item->Frame() != aPopup) {
|
||||
if (item->IsContextMenu())
|
||||
return PR_TRUE;
|
||||
|
@ -1050,7 +1065,8 @@ nsXULPopupManager::HasContextMenu(nsMenuPopupFrame* aPopup)
|
|||
void
|
||||
nsXULPopupManager::SetCaptureState(nsIContent* aOldPopup)
|
||||
{
|
||||
if (mCurrentMenu && aOldPopup == mCurrentMenu->Content())
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
if (item && aOldPopup == item->Content())
|
||||
return;
|
||||
|
||||
if (mWidget) {
|
||||
|
@ -1058,8 +1074,8 @@ nsXULPopupManager::SetCaptureState(nsIContent* aOldPopup)
|
|||
mWidget = nsnull;
|
||||
}
|
||||
|
||||
if (mCurrentMenu) {
|
||||
nsMenuPopupFrame* popup = mCurrentMenu->Frame();
|
||||
if (item) {
|
||||
nsMenuPopupFrame* popup = item->Frame();
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
popup->GetWidget(getter_AddRefs(widget));
|
||||
if (widget) {
|
||||
|
@ -1076,9 +1092,10 @@ void
|
|||
nsXULPopupManager::UpdateKeyboardListeners()
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> newTarget;
|
||||
if (mCurrentMenu) {
|
||||
if (!mCurrentMenu->IgnoreKeys())
|
||||
newTarget = do_QueryInterface(mCurrentMenu->Content()->GetDocument());
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
if (item) {
|
||||
if (!item->IgnoreKeys())
|
||||
newTarget = do_QueryInterface(item->Content()->GetDocument());
|
||||
}
|
||||
else if (mActiveMenuBar) {
|
||||
newTarget = do_QueryInterface(mActiveMenuBar->GetContent()->GetDocument());
|
||||
|
@ -1226,8 +1243,9 @@ PRBool
|
|||
nsXULPopupManager::HandleShortcutNavigation(nsIDOMKeyEvent* aKeyEvent,
|
||||
nsMenuPopupFrame* aFrame)
|
||||
{
|
||||
if (!aFrame && mCurrentMenu)
|
||||
aFrame = mCurrentMenu->Frame();
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
if (!aFrame && item)
|
||||
aFrame = item->Frame();
|
||||
|
||||
if (aFrame) {
|
||||
PRBool action;
|
||||
|
@ -1266,7 +1284,7 @@ nsXULPopupManager::HandleKeyboardNavigation(PRUint32 aKeyCode)
|
|||
// navigate up through the open menus, looking for the topmost one
|
||||
// in the same hierarchy
|
||||
nsMenuChainItem* item = nsnull;
|
||||
nsMenuChainItem* nextitem = mCurrentMenu;
|
||||
nsMenuChainItem* nextitem = GetTopVisibleMenu();
|
||||
|
||||
while (nextitem) {
|
||||
item = nextitem;
|
||||
|
@ -1609,8 +1627,9 @@ nsXULPopupManager::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
}
|
||||
else if (theChar == NS_VK_ESCAPE) {
|
||||
// Pressing Escape hides one level of menus only
|
||||
if (mCurrentMenu)
|
||||
HidePopup(mCurrentMenu->Content(), PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
if (item)
|
||||
HidePopup(item->Content(), PR_FALSE, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
else if (theChar == NS_VK_TAB) {
|
||||
Rollup();
|
||||
|
@ -1621,8 +1640,9 @@ nsXULPopupManager::KeyPress(nsIDOMEvent* aKeyEvent)
|
|||
// Otherwise, tell the active menubar, if any, to activate the menu. The
|
||||
// Enter method will return a menu if one needs to be opened as a result.
|
||||
nsMenuFrame* menuToOpen = nsnull;
|
||||
if (mCurrentMenu)
|
||||
menuToOpen = mCurrentMenu->Frame()->Enter();
|
||||
nsMenuChainItem* item = GetTopVisibleMenu();
|
||||
if (item)
|
||||
menuToOpen = item->Frame()->Enter();
|
||||
else if (mActiveMenuBar)
|
||||
menuToOpen = mActiveMenuBar->Enter();
|
||||
if (menuToOpen) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче