Simplify/optimize Mac OS X native menu open/close, reduce carbon menu usage. b=510243 r=smichaud

This commit is contained in:
Josh Aas 2009-08-13 20:01:57 -04:00
Родитель bee5f4b25f
Коммит 556afaec46
3 изменённых файлов: 44 добавлений и 107 удалений

Просмотреть файл

@ -278,11 +278,8 @@ void nsMenuBarX::ForceUpdateNativeMenuAt(const nsAString& indexString)
return; return;
// fake open/close to cause lazy update to happen so submenus populate // fake open/close to cause lazy update to happen so submenus populate
nsMenuEvent menuEvent(PR_TRUE, NS_MENU_SELECTED, nsnull); currentMenu->MenuOpened();
menuEvent.time = PR_IntervalNow(); currentMenu->MenuClosed();
menuEvent.mCommand = (PRUint32)_NSGetCarbonMenu(static_cast<NSMenu*>(currentMenu->NativeData()));
currentMenu->MenuOpened(menuEvent);
currentMenu->MenuClosed(menuEvent);
// now find the correct submenu // now find the correct submenu
for (unsigned int i = 1; currentMenu && i < indexCount; i++) { for (unsigned int i = 1; currentMenu && i < indexCount; i++) {
@ -298,11 +295,8 @@ void nsMenuBarX::ForceUpdateNativeMenuAt(const nsAString& indexString)
if (targetMenu->MenuObjectType() == eSubmenuObjectType && visible == (targetIndex + 1)) { if (targetMenu->MenuObjectType() == eSubmenuObjectType && visible == (targetIndex + 1)) {
currentMenu = static_cast<nsMenuX*>(targetMenu); currentMenu = static_cast<nsMenuX*>(targetMenu);
// fake open/close to cause lazy update to happen // fake open/close to cause lazy update to happen
nsMenuEvent menuEvent(PR_TRUE, NS_MENU_SELECTED, nsnull); currentMenu->MenuOpened();
menuEvent.time = PR_IntervalNow(); currentMenu->MenuClosed();
menuEvent.mCommand = (PRUint32)_NSGetCarbonMenu(static_cast<NSMenu*>(currentMenu->NativeData()));
currentMenu->MenuOpened(menuEvent);
currentMenu->MenuClosed(menuEvent);
break; break;
} }
} }

Просмотреть файл

@ -59,7 +59,6 @@ class nsIWidget;
{ {
nsMenuX* mGeckoMenu; // weak ref nsMenuX* mGeckoMenu; // weak ref
EventHandlerRef mEventHandler; EventHandlerRef mEventHandler;
BOOL mHaveInstalledCarbonEvents;
} }
- (id)initWithGeckoMenu:(nsMenuX*)geckoMenu; - (id)initWithGeckoMenu:(nsMenuX*)geckoMenu;
@end @end
@ -90,8 +89,8 @@ public:
nsMenuObjectX* GetItemAt(PRUint32 aPos); nsMenuObjectX* GetItemAt(PRUint32 aPos);
nsresult GetVisibleItemCount(PRUint32 &aCount); nsresult GetVisibleItemCount(PRUint32 &aCount);
nsMenuObjectX* GetVisibleItemAt(PRUint32 aPos); nsMenuObjectX* GetVisibleItemAt(PRUint32 aPos);
nsEventStatus MenuOpened(const nsMenuEvent& aMenuEvent); nsEventStatus MenuOpened();
void MenuClosed(const nsMenuEvent& aMenuEvent); void MenuClosed();
void SetRebuild(PRBool aMenuEvent); void SetRebuild(PRBool aMenuEvent);
NSMenuItem* NativeMenuItem(); NSMenuItem* NativeMenuItem();
@ -103,9 +102,7 @@ protected:
nsresult SetupIcon(); nsresult SetupIcon();
void GetMenuPopupContent(nsIContent** aResult); void GetMenuPopupContent(nsIContent** aResult);
PRBool OnOpen(); PRBool OnOpen();
PRBool OnOpened();
PRBool OnClose(); PRBool OnClose();
PRBool OnClosed();
nsresult AddMenuItem(nsMenuItemX* aMenuItem); nsresult AddMenuItem(nsMenuItemX* aMenuItem);
nsresult AddMenu(nsMenuX* aMenu); nsresult AddMenu(nsMenuX* aMenu);
void LoadMenuItem(nsIContent* inMenuItemContent); void LoadMenuItem(nsIContent* inMenuItemContent);

Просмотреть файл

@ -312,56 +312,37 @@ nsresult nsMenuX::RemoveAll()
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
} }
nsEventStatus nsMenuX::MenuOpened(const nsMenuEvent & aMenuEvent) nsEventStatus nsMenuX::MenuOpened()
{ {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; // Open the node.
mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::open, NS_LITERAL_STRING("true"), PR_TRUE);
// Determine if this is the correct menu to handle the event // Fire a handler. If we're told to stop, don't build the menu at all
MenuRef selectedMenuHandle = (MenuRef)aMenuEvent.mCommand; PRBool keepProcessing = OnOpen();
// at this point, the carbon event handler was installed so there if (!mNeedsRebuild || !keepProcessing)
// must be a carbon MenuRef to be had return nsEventStatus_eConsumeNoDefault;
if (_NSGetCarbonMenu(mNativeMenu) == selectedMenuHandle) {
// Open the node.
mContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::open, NS_LITERAL_STRING("true"), PR_TRUE);
// Fire a handler. If we're told to stop, don't build the menu at all if (!mConstructed || mNeedsRebuild) {
PRBool keepProcessing = OnOpen(); if (mNeedsRebuild)
RemoveAll();
if (!mNeedsRebuild || !keepProcessing) MenuConstruct();
return nsEventStatus_eConsumeNoDefault; mConstructed = true;
if (!mConstructed || mNeedsRebuild) {
if (mNeedsRebuild)
RemoveAll();
MenuConstruct();
mConstructed = true;
}
OnOpened();
return nsEventStatus_eConsumeNoDefault;
}
else {
// Make sure none of our submenus are the ones that should be handling this
PRUint32 count = mMenuObjectsArray.Length();
for (PRUint32 i = 0; i < count; i++) {
nsMenuObjectX* menuObject = mMenuObjectsArray[i];
if (menuObject->MenuObjectType() == eSubmenuObjectType) {
nsEventStatus status = static_cast<nsMenuX*>(menuObject)->MenuOpened(aMenuEvent);
if (status != nsEventStatus_eIgnore)
return status;
}
}
} }
return nsEventStatus_eIgnore; nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_SHOWN, nsnull, nsMouseEvent::eReal);
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nsEventStatus_eIgnore); nsCOMPtr<nsIContent> popupContent;
GetMenuPopupContent(getter_AddRefs(popupContent));
nsIContent* dispatchTo = popupContent ? popupContent : mContent;
dispatchTo->DispatchDOMEvent(&event, nsnull, nsnull, &status);
return nsEventStatus_eConsumeNoDefault;
} }
void nsMenuX::MenuClosed(const nsMenuEvent & aMenuEvent) void nsMenuX::MenuClosed()
{ {
if (mConstructed) { if (mConstructed) {
// Don't close if a handler tells us to stop. // Don't close if a handler tells us to stop.
@ -373,8 +354,15 @@ void nsMenuX::MenuClosed(const nsMenuEvent & aMenuEvent)
mContent->UnsetAttr(kNameSpaceID_None, nsWidgetAtoms::open, PR_TRUE); mContent->UnsetAttr(kNameSpaceID_None, nsWidgetAtoms::open, PR_TRUE);
OnClosed(); nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_HIDDEN, nsnull, nsMouseEvent::eReal);
nsCOMPtr<nsIContent> popupContent;
GetMenuPopupContent(getter_AddRefs(popupContent));
nsIContent* dispatchTo = popupContent ? popupContent : mContent;
dispatchTo->DispatchDOMEvent(&event, nsnull, nsnull, &status);
mDestroyHandlerCalled = PR_TRUE;
mConstructed = false; mConstructed = false;
} }
} }
@ -629,23 +617,6 @@ PRBool nsMenuX::OnOpen()
return PR_TRUE; return PR_TRUE;
} }
PRBool nsMenuX::OnOpened()
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_SHOWN, nsnull, nsMouseEvent::eReal);
nsCOMPtr<nsIContent> popupContent;
GetMenuPopupContent(getter_AddRefs(popupContent));
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mContent;
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, nsnull, &status);
if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault)
return PR_FALSE;
return PR_TRUE;
}
// Returns TRUE if we should keep processing the event, FALSE if the handler // Returns TRUE if we should keep processing the event, FALSE if the handler
// wants to stop the closing of the menu. // wants to stop the closing of the menu.
PRBool nsMenuX::OnClose() PRBool nsMenuX::OnClose()
@ -672,27 +643,6 @@ PRBool nsMenuX::OnClose()
return PR_TRUE; return PR_TRUE;
} }
PRBool nsMenuX::OnClosed()
{
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event(PR_TRUE, NS_XUL_POPUP_HIDDEN, nsnull,
nsMouseEvent::eReal);
nsCOMPtr<nsIContent> popupContent;
GetMenuPopupContent(getter_AddRefs(popupContent));
nsresult rv = NS_OK;
nsIContent* dispatchTo = popupContent ? popupContent : mContent;
rv = dispatchTo->DispatchDOMEvent(&event, nsnull, nsnull, &status);
mDestroyHandlerCalled = PR_TRUE;
if (NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault)
return PR_FALSE;
return PR_TRUE;
}
// Find the |menupopup| child in the |popup| representing this menu. It should be one // Find the |menupopup| child in the |popup| representing this menu. It should be one
// of a very few children so we won't be iterating over a bazillion menu items to find // of a very few children so we won't be iterating over a bazillion menu items to find
// it (so the strcmp won't kill us). // it (so the strcmp won't kill us).
@ -881,15 +831,10 @@ static pascal OSStatus MyMenuEventHandler(EventHandlerCallRef myHandler, EventRe
gRollupListener->Rollup(nsnull, nsnull); gRollupListener->Rollup(nsnull, nsnull);
return userCanceledErr; return userCanceledErr;
} }
MenuRef menuRef;
::GetEventParameter(event, kEventParamDirectObject, typeMenuRef, NULL, sizeof(menuRef), NULL, &menuRef);
nsMenuEvent menuEvent(PR_TRUE, NS_MENU_SELECTED, nsnull);
menuEvent.time = PR_IntervalNow();
menuEvent.mCommand = (PRUint32)menuRef;
if (kind == kEventMenuOpening) if (kind == kEventMenuOpening)
targetMenu->MenuOpened(menuEvent); targetMenu->MenuOpened();
else else
targetMenu->MenuClosed(menuEvent); targetMenu->MenuClosed();
return noErr; return noErr;
} }
return eventNotHandledErr; return eventNotHandledErr;
@ -928,8 +873,9 @@ static OSStatus InstallMyMenuEventHandler(MenuRef menuRef, void* userData, Event
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if ((self = [super init])) { if ((self = [super init])) {
NS_ASSERTION(geckoMenu, "Cannot initialize native menu delegate with NULL gecko menu! Will crash!");
mGeckoMenu = geckoMenu; mGeckoMenu = geckoMenu;
mHaveInstalledCarbonEvents = FALSE; mEventHandler = NULL;
} }
return self; return self;
@ -941,7 +887,9 @@ static OSStatus InstallMyMenuEventHandler(MenuRef menuRef, void* userData, Event
{ {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK; NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
RemoveEventHandler(mEventHandler); if (mEventHandler)
::RemoveEventHandler(mEventHandler);
[super dealloc]; [super dealloc];
NS_OBJC_END_TRY_ABORT_BLOCK; NS_OBJC_END_TRY_ABORT_BLOCK;
@ -957,12 +905,10 @@ static OSStatus InstallMyMenuEventHandler(MenuRef menuRef, void* userData, Event
{ {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK; NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!mHaveInstalledCarbonEvents) { if (!mEventHandler) {
MenuRef myMenuRef = _NSGetCarbonMenu(aMenu); MenuRef myMenuRef = _NSGetCarbonMenu(aMenu);
if (myMenuRef) { if (myMenuRef)
InstallMyMenuEventHandler(myMenuRef, mGeckoMenu, &mEventHandler); InstallMyMenuEventHandler(myMenuRef, mGeckoMenu, &mEventHandler);
mHaveInstalledCarbonEvents = TRUE;
}
} }
NS_OBJC_END_TRY_ABORT_BLOCK; NS_OBJC_END_TRY_ABORT_BLOCK;