зеркало из https://github.com/mozilla/pjs.git
Fix the menu code to not hold onto webshells, and to use weak refs for the previous menu stack etc. This allows menus to be cleaned up properly on quit (look ma, no leaks!). Bug 41695. r=saari, pinkerton
This commit is contained in:
Родитель
bfc9ac7f98
Коммит
ebebf4829d
|
@ -32,18 +32,17 @@
|
|||
#include <MixedMode.h>
|
||||
#include <A4Stuff.h>
|
||||
|
||||
extern nsIMenuBar * gMacMenubar;
|
||||
extern Handle gSystemMDEFHandle;
|
||||
extern nsWeakPtr gMacMenubar;
|
||||
extern Handle gSystemMDEFHandle;
|
||||
|
||||
#pragma options align=mac68k
|
||||
RoutineDescriptorPtr gOriginaldesc;
|
||||
RoutineDescriptorPtr gmdefUPP;
|
||||
|
||||
// Caching the Mac menu
|
||||
nsVoidArray gPreviousMenuHandleStack;
|
||||
nsVoidArray gPreviousMenuStack; // Strong references kept!
|
||||
|
||||
nsCOMPtr<nsIMenuBar> gPreviousMenuBar;
|
||||
nsVoidArray gPreviousMenuHandleStack; // hold MenuHandles
|
||||
nsMenuStack gPreviousMenuStack; // weak refs
|
||||
nsWeakPtr gPreviousMenuBar; // weak ref
|
||||
|
||||
MenuHandle gSizedMenu = nsnull;
|
||||
|
||||
|
@ -68,6 +67,58 @@ nsIMenu * gPreviousTopLevelMenu = nsnull;
|
|||
nsIMenu * gPreviousMenu = nsnull;
|
||||
MenuHandle gPreviousMenuHandle = nsnull;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
nsMenuStack::nsMenuStack()
|
||||
{
|
||||
}
|
||||
|
||||
nsMenuStack::~nsMenuStack()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMenuStack::GetMenuAt(PRInt32 aIndex, nsIMenu **outMenu)
|
||||
{
|
||||
nsCOMPtr<nsISupports> elementPtr = getter_AddRefs(mMenuArray.ElementAt(aIndex));
|
||||
if (!elementPtr)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(elementPtr);
|
||||
return weakRef->QueryReferent(NS_GET_IID(nsIMenu), NS_REINTERPRET_CAST(void**, outMenu));
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsMenuStack::HaveMenuAt(PRInt32 aIndex)
|
||||
{
|
||||
nsCOMPtr<nsISupports> elementPtr = getter_AddRefs(mMenuArray.ElementAt(aIndex));
|
||||
if (!elementPtr)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIWeakReference> weakRef = do_QueryInterface(elementPtr);
|
||||
nsCOMPtr<nsIMenu> theMenu = do_QueryReferent(weakRef);
|
||||
return (theMenu.get() != nsnull);
|
||||
}
|
||||
|
||||
PRBool nsMenuStack::RemoveMenuAt(PRInt32 aIndex)
|
||||
{
|
||||
return mMenuArray.RemoveElementAt(aIndex);
|
||||
}
|
||||
|
||||
PRBool nsMenuStack::InsertMenuAt(nsIMenu* inMenuItem, PRInt32 aIndex)
|
||||
{
|
||||
nsCOMPtr<nsISupportsWeakReference> weakRefFactory = do_QueryInterface(inMenuItem);
|
||||
if (!weakRefFactory) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsISupports> observerRef = getter_AddRefs(NS_STATIC_CAST(nsISupports*, NS_GetWeakReference(weakRefFactory)));
|
||||
if (!observerRef) return NS_ERROR_NULL_POINTER;
|
||||
return mMenuArray.InsertElementAt(observerRef, aIndex);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Internal functions
|
||||
|
||||
|
@ -129,7 +180,7 @@ pascal void nsDynamicMDEFMain(
|
|||
Rect * menuRect,
|
||||
Point hitPt,
|
||||
short * whichItem)
|
||||
{
|
||||
{
|
||||
switch (message) {
|
||||
case kMenuDrawMsg:
|
||||
//printf(" Draw passed in menu is = %d \n", *theMenu);
|
||||
|
@ -157,44 +208,48 @@ pascal void nsDynamicMDEFMain(
|
|||
nsCheckDestroy(theMenu, whichItem);
|
||||
|
||||
// Need to make sure that we rebuild the menu every time...
|
||||
if (gPreviousMenuHandleStack.Count()) {
|
||||
nsIMenu * menu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
MenuHandle menuHandle = (MenuHandle) gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1];
|
||||
|
||||
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
|
||||
if (gPreviousMenuHandleStack.Count())
|
||||
{
|
||||
nsCOMPtr<nsIMenu> menu;
|
||||
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(menu));
|
||||
// nsIMenu * menu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
MenuHandle menuHandle = (MenuHandle) gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1];
|
||||
|
||||
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
|
||||
|
||||
if( menu && menuHandle ) {
|
||||
|
||||
if( menuHandle == theMenu ) {
|
||||
|
||||
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
|
||||
if(listener) {
|
||||
//printf("MenuPop \n");
|
||||
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
mevent.time = PR_IntervalNow();
|
||||
mevent.mCommand = (PRUint32) nsnull;
|
||||
|
||||
// UNDO
|
||||
listener->MenuDeselected(mevent);
|
||||
|
||||
//gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1);
|
||||
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
|
||||
//NS_IF_RELEASE(menu);
|
||||
|
||||
//printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count());
|
||||
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( menu && menuHandle ) {
|
||||
|
||||
if( menuHandle == theMenu ) {
|
||||
|
||||
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
|
||||
if(listener) {
|
||||
//printf("MenuPop \n");
|
||||
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
mevent.time = PR_IntervalNow();
|
||||
mevent.mCommand = (PRUint32) nsnull;
|
||||
|
||||
// UNDO
|
||||
listener->MenuDeselected(mevent);
|
||||
|
||||
gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1);
|
||||
NS_IF_RELEASE(menu);
|
||||
|
||||
//printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count());
|
||||
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsDynamicSizeTheMenu(theMenu);
|
||||
break;
|
||||
}
|
||||
|
@ -205,7 +260,7 @@ if (gPreviousMenuHandleStack.Count()) {
|
|||
SInt8 state = ::HGetState((Handle)theMenu);
|
||||
HLock((Handle)theMenu);
|
||||
(**theMenu).menuWidth = -1;
|
||||
(**theMenu).menuHeight = -1;
|
||||
(**theMenu).menuHeight = -1;
|
||||
HSetState((Handle)theMenu, state);
|
||||
}
|
||||
}
|
||||
|
@ -285,8 +340,9 @@ void nsDoMagic(MenuHandle theMenu)
|
|||
// ask if this is a child of the previous menu
|
||||
PRBool isChild = PR_FALSE;
|
||||
|
||||
if(gPreviousMenuStack.Count() > 0) {
|
||||
if(gPreviousMenuStack[gPreviousMenuStack.Count() - 1]) {
|
||||
if (gPreviousMenuStack.Count() > 0)
|
||||
{
|
||||
if (gPreviousMenuStack.HaveMenuAt(gPreviousMenuStack.Count() - 1)) {
|
||||
if(nsIsHierChild(theMenu)) {
|
||||
isChild = PR_TRUE;
|
||||
}
|
||||
|
@ -304,7 +360,7 @@ void nsDoMagic(MenuHandle theMenu)
|
|||
} else {
|
||||
gCurrentMenuDepth = 1;
|
||||
}
|
||||
|
||||
|
||||
nsBuildMenu(theMenu, isChild);
|
||||
}
|
||||
|
||||
|
@ -312,9 +368,8 @@ void nsDoMagic(MenuHandle theMenu)
|
|||
void nsBuildMenu(MenuHandle theMenu, PRBool isChild)
|
||||
{
|
||||
// printf("enter BuildMenu \n");
|
||||
nsIMenuBar * menubar = gMacMenubar; // Global for current menubar
|
||||
|
||||
if(!menubar || !theMenu) {
|
||||
nsCOMPtr<nsIMenuBar> menubar = do_QueryReferent(gMacMenubar);
|
||||
if (!menubar || !theMenu) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -329,25 +384,25 @@ void nsBuildMenu(MenuHandle theMenu, PRBool isChild)
|
|||
|
||||
// If toplevel
|
||||
if( gCurrentMenuDepth < 2 ) {
|
||||
PRUint32 numMenus = 0;
|
||||
menubar->GetMenuCount(numMenus);
|
||||
numMenus--;
|
||||
for(PRInt32 i = numMenus; i >= 0; i--) {
|
||||
nsCOMPtr<nsIMenu> menu;
|
||||
menubar->GetMenuAt(i, *getter_AddRefs(menu));
|
||||
if(menu) {
|
||||
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
|
||||
if(listener) {
|
||||
// Reset menu depth count
|
||||
gMenuDepth = 0;
|
||||
nsEventStatus status = listener->MenuSelected(mevent);
|
||||
if(status != nsEventStatus_eIgnore) {
|
||||
|
||||
PRUint32 numMenus = 0;
|
||||
menubar->GetMenuCount(numMenus);
|
||||
numMenus--;
|
||||
for(PRInt32 i = numMenus; i >= 0; i--) {
|
||||
nsCOMPtr<nsIMenu> menu;
|
||||
menubar->GetMenuAt(i, *getter_AddRefs(menu));
|
||||
if(menu) {
|
||||
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
|
||||
if(listener) {
|
||||
// Reset menu depth count
|
||||
gMenuDepth = 0;
|
||||
nsEventStatus status = listener->MenuSelected(mevent);
|
||||
if(status != nsEventStatus_eIgnore)
|
||||
{
|
||||
nsPostBuild(menu, theMenu, isChild);
|
||||
gPreviousTopLevelMenuHandle = theMenu;
|
||||
gPreviousTopLevelMenu = menu;
|
||||
gPreviousMenuBar = menubar;
|
||||
|
||||
gPreviousTopLevelMenuHandle = theMenu;
|
||||
gPreviousTopLevelMenu = menu;
|
||||
|
||||
gPreviousMenuBar = getter_AddRefs(NS_GetWeakReference(menubar));
|
||||
//printf("exit BuildMenu \n");
|
||||
return;
|
||||
}
|
||||
|
@ -358,24 +413,30 @@ void nsBuildMenu(MenuHandle theMenu, PRBool isChild)
|
|||
// Not top level, so we can't use recursive MenuSelect <sigh>
|
||||
// We must use the previously chosen menu item in combination
|
||||
// with the current menu to determine what menu needs to be constructed
|
||||
nsISupports * supports = nsnull;
|
||||
//printf("gCurrentMenuItem = %d \n", gCurrentMenuItem);
|
||||
if(gCurrentMenuItem) {
|
||||
if(gPreviousMenuStack.Count() > 0) {
|
||||
nsIMenu * prevMenu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
//printf("gCurrentMenuItem = %d \n", gCurrentMenuItem);
|
||||
if (gCurrentMenuItem){
|
||||
if (gPreviousMenuStack.Count() > 0)
|
||||
{
|
||||
nsCOMPtr<nsIMenu> prevMenu;
|
||||
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(prevMenu));
|
||||
|
||||
//nsIMenu * prevMenu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
//printf("gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count() );
|
||||
|
||||
if(prevMenu) {
|
||||
prevMenu->GetItemAt(gCurrentMenuItem - 1, supports);
|
||||
nsCOMPtr<nsIMenu> menu(do_QueryInterface(supports));
|
||||
if(menu) {
|
||||
nsCOMPtr<nsIMenuListener> menulistener(do_QueryInterface(supports));
|
||||
menulistener->MenuSelected(mevent);
|
||||
nsPostBuild(menu, theMenu, isChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(prevMenu)
|
||||
{
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
prevMenu->GetItemAt(gCurrentMenuItem - 1, *getter_AddRefs(supports));
|
||||
nsCOMPtr<nsIMenu> menu = do_QueryInterface(supports);
|
||||
if (menu)
|
||||
{
|
||||
nsCOMPtr<nsIMenuListener> menulistener = do_QueryInterface(menu);
|
||||
menulistener->MenuSelected(mevent);
|
||||
nsPostBuild(menu, theMenu, isChild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf("exit BuildMenu \n");
|
||||
}
|
||||
|
@ -383,15 +444,13 @@ void nsBuildMenu(MenuHandle theMenu, PRBool isChild)
|
|||
//------------------------------------------------------------------------------
|
||||
void nsPostBuild(nsIMenu * menu, MenuHandle theMenu, PRBool isChild)
|
||||
{
|
||||
// it is built now
|
||||
if(isChild || (gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1] != theMenu)) {
|
||||
nsPushMenu(menu);
|
||||
NS_IF_ADDREF(menu);
|
||||
|
||||
nsPushMenuHandle(theMenu);
|
||||
|
||||
//printf("Push: %d items in gMenuHandleStack \n", gMenuHandleStack.Count());
|
||||
}
|
||||
// it is built now
|
||||
if(isChild || (gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1] != theMenu))
|
||||
{
|
||||
nsPushMenu(menu);
|
||||
nsPushMenuHandle(theMenu);
|
||||
//printf("Push: %d items in gMenuHandleStack \n", gMenuHandleStack.Count());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
@ -402,92 +461,112 @@ void nsCallSystemMDEF(
|
|||
Point hitPt,
|
||||
short * whichItem)
|
||||
{
|
||||
SInt8 state = ::HGetState(gSystemMDEFHandle);
|
||||
::HLock(gSystemMDEFHandle);
|
||||
SInt8 state = ::HGetState(gSystemMDEFHandle);
|
||||
::HLock(gSystemMDEFHandle);
|
||||
|
||||
gmdefUPP = ::NewRoutineDescriptor( (ProcPtr)*gSystemMDEFHandle, uppMenuDefProcInfo, kM68kISA);
|
||||
gmdefUPP = ::NewRoutineDescriptor( (ProcPtr)*gSystemMDEFHandle, uppMenuDefProcInfo, kM68kISA);
|
||||
|
||||
CallMenuDefProc(
|
||||
gmdefUPP,
|
||||
message,
|
||||
theMenu,
|
||||
menuRect,
|
||||
hitPt,
|
||||
whichItem);
|
||||
CallMenuDefProc(
|
||||
gmdefUPP,
|
||||
message,
|
||||
theMenu,
|
||||
menuRect,
|
||||
hitPt,
|
||||
whichItem);
|
||||
|
||||
::DisposeRoutineDescriptor(gmdefUPP);
|
||||
::HSetState(gSystemMDEFHandle, state);
|
||||
::DisposeRoutineDescriptor(gmdefUPP);
|
||||
::HSetState(gSystemMDEFHandle, state);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void nsPushMenu(nsIMenu * aMenu)
|
||||
void nsPushMenu(nsIMenu *aMenu)
|
||||
{
|
||||
gPreviousMenuStack.InsertElementAt(aMenu, gPreviousMenuStack.Count());
|
||||
gPreviousMenuStack.InsertMenuAt(aMenu, gPreviousMenuStack.Count());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void nsPopMenu(nsIMenu ** aMenu)
|
||||
{
|
||||
if(gPreviousMenuStack.Count() > 0) {
|
||||
*aMenu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1);
|
||||
if(gPreviousMenuStack.Count() > 0)
|
||||
{
|
||||
// *aMenu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, aMenu);
|
||||
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
|
||||
} else
|
||||
*aMenu = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void nsPreviousMenuStackUnwind(nsIMenu * aMenuJustBuilt, MenuHandle aMenuHandleJustBuilt)
|
||||
{
|
||||
PRBool shouldReleaseMenubar = PR_FALSE;
|
||||
//PRBool shouldReleaseMenubar = PR_FALSE;
|
||||
|
||||
//printf("PreviousMenuStackUnwind called \n");
|
||||
//printf("%d items on gPreviousMenuStack \n", gPreviousMenuStack.Count());
|
||||
while (gPreviousMenuHandleStack.Count()) {
|
||||
nsIMenu * menu = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
while (gPreviousMenuHandleStack.Count())
|
||||
{
|
||||
nsCOMPtr<nsIMenu> menu; // = (nsIMenu *) gPreviousMenuStack[gPreviousMenuStack.Count() - 1];
|
||||
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(menu));
|
||||
|
||||
MenuHandle menuHandle = (MenuHandle) gPreviousMenuHandleStack[gPreviousMenuHandleStack.Count() - 1];
|
||||
|
||||
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
|
||||
|
||||
if( menu && menuHandle ) {
|
||||
if (menu)
|
||||
{
|
||||
|
||||
if( menuHandle != aMenuHandleJustBuilt ) {
|
||||
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
|
||||
if(listener) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
mevent.time = PR_IntervalNow();
|
||||
mevent.mCommand = (PRUint32) nsnull;
|
||||
|
||||
// UNDO
|
||||
listener->MenuDeselected(mevent);
|
||||
|
||||
gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1);
|
||||
NS_IF_RELEASE(menu);
|
||||
shouldReleaseMenubar = PR_TRUE;
|
||||
|
||||
//printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count());
|
||||
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
|
||||
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
|
||||
|
||||
if( menuHandle ) {
|
||||
|
||||
if( menuHandle != aMenuHandleJustBuilt ) {
|
||||
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menu));
|
||||
if(listener) {
|
||||
nsMenuEvent mevent;
|
||||
mevent.message = NS_MENU_SELECTED;
|
||||
mevent.eventStructType = NS_MENU_EVENT;
|
||||
mevent.point.x = 0;
|
||||
mevent.point.y = 0;
|
||||
mevent.widget = nsnull;
|
||||
mevent.time = PR_IntervalNow();
|
||||
mevent.mCommand = (PRUint32) nsnull;
|
||||
|
||||
// UNDO
|
||||
listener->MenuDeselected(mevent);
|
||||
|
||||
//gPreviousMenuStack.RemoveElementAt(gPreviousMenuStack.Count() - 1);
|
||||
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
|
||||
// NS_IF_RELEASE(menu);
|
||||
//shouldReleaseMenubar = PR_TRUE;
|
||||
|
||||
//printf("%d items now on gPreviousMenuStack \n", gPreviousMenuStack.Count());
|
||||
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
|
||||
|
||||
// we are the aMenuHandleJustBuilt
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove the weak ref
|
||||
gPreviousMenuStack.RemoveMenuAt(gPreviousMenuStack.Count() - 1);
|
||||
NS_ASSERTION(menuHandle != aMenuHandleJustBuilt, "Got the menu handle just built");
|
||||
if( menuHandle )
|
||||
gPreviousMenuHandleStack.RemoveElementAt(gPreviousMenuHandleStack.Count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// relinquish hold of the menubar _after_ releasing the menu so it can finish
|
||||
// unregistering itself.
|
||||
if ( shouldReleaseMenubar )
|
||||
gPreviousMenuBar = nsnull;
|
||||
//if ( shouldReleaseMenubar )
|
||||
// gPreviousMenuBar = nsnull;
|
||||
|
||||
//printf(" gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
//printf(" gPreviousMenuHandleStack.Count() = %d \n", gPreviousMenuHandleStack.Count());
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
#ifndef nsDynamicMDEF_h__
|
||||
#define nsDynamicMDEF_h__
|
||||
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsIMenu.h"
|
||||
|
||||
#include <Menus.h>
|
||||
|
||||
pascal void nsDynamicMDEFMain(
|
||||
|
@ -40,4 +42,69 @@ void nsPreviousMenuStackUnwind(
|
|||
MenuHandle aMenuHandleJustBuilt);
|
||||
|
||||
|
||||
// helper class useful for counting instances
|
||||
class nsInstanceCounter
|
||||
{
|
||||
public:
|
||||
nsInstanceCounter(const char* inDesc)
|
||||
: mInstanceCount(0)
|
||||
, mDescription(inDesc)
|
||||
{
|
||||
}
|
||||
|
||||
~nsInstanceCounter()
|
||||
{
|
||||
printf("%s %ld\n", mDescription, mInstanceCount);
|
||||
}
|
||||
|
||||
nsInstanceCounter& operator ++() // prefix
|
||||
{
|
||||
++ mInstanceCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
nsInstanceCounter& operator -- () // prefix
|
||||
{
|
||||
-- mInstanceCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
PRInt32 mInstanceCount;
|
||||
const char* mDescription;
|
||||
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class nsMenuStack
|
||||
{
|
||||
public:
|
||||
nsMenuStack();
|
||||
~nsMenuStack();
|
||||
|
||||
|
||||
PRInt32 Count()
|
||||
{
|
||||
PRUint32 num;
|
||||
mMenuArray.Count(&num);
|
||||
return (PRInt32)num;
|
||||
}
|
||||
|
||||
// returns addreffed nsIMenu
|
||||
nsresult GetMenuAt(PRInt32 aIndex, nsIMenu **outMenu);
|
||||
PRBool HaveMenuAt(PRInt32 aIndex);
|
||||
PRBool RemoveMenuAt(PRInt32 aIndex); // no release
|
||||
PRBool InsertMenuAt(nsIMenu* aElement, PRInt32 aIndex); // no addrefs; weak ref.
|
||||
|
||||
protected:
|
||||
|
||||
nsSupportsArray mMenuArray; // array of weak refs to nsIMenus
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif nsDynamicMDEF_h__
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -25,9 +25,10 @@
|
|||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMenu.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsIChangeManager.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#include <Menus.h>
|
||||
#include <UnicodeConverter.h>
|
||||
|
@ -38,14 +39,14 @@ class nsIDOMElement;
|
|||
|
||||
|
||||
// temporary hack to get apple menu -- sfraser, approved saari
|
||||
#define APPLE_MENU_HACK 1
|
||||
#define APPLE_MENU_HACK 1
|
||||
|
||||
#ifdef APPLE_MENU_HACK
|
||||
extern const PRInt16 kMacMenuID;
|
||||
extern const PRInt16 kAppleMenuID;
|
||||
#endif /* APPLE_MENU_HACK */
|
||||
|
||||
//static PRInt16 mMacMenuIDCount; // use GetUniqueMenuID()
|
||||
//static PRInt16 mMacMenuIDCount; // use GetUniqueMenuID()
|
||||
extern PRInt16 mMacMenuIDCount;// = kMacMenuID;
|
||||
|
||||
|
||||
|
@ -56,7 +57,10 @@ namespace MenuHelpers
|
|||
}
|
||||
|
||||
|
||||
class nsMenu : public nsIMenu, public nsIMenuListener, public nsIChangeObserver
|
||||
class nsMenu : public nsIMenu,
|
||||
public nsIMenuListener,
|
||||
public nsIChangeObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
|
||||
public:
|
||||
|
@ -103,35 +107,34 @@ public:
|
|||
NS_IMETHOD AddMenu(nsIMenu * aMenu);
|
||||
|
||||
// MacSpecific
|
||||
static PRInt16 GetUniqueMenuID() {
|
||||
if (mMacMenuIDCount == 32767)
|
||||
mMacMenuIDCount = 256;
|
||||
return mMacMenuIDCount++;
|
||||
}
|
||||
static PRInt16 GetUniqueMenuID()
|
||||
{
|
||||
if (mMacMenuIDCount == 32767)
|
||||
mMacMenuIDCount = 256;
|
||||
return mMacMenuIDCount++;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsString mLabel;
|
||||
PRUint32 mNumMenuItems;
|
||||
nsVoidArray mMenuItemVoidArray;
|
||||
nsString mLabel;
|
||||
PRUint32 mNumMenuItems;
|
||||
nsSupportsArray mMenuItemsArray; // array holds refs
|
||||
|
||||
nsIMenu * mMenuParent; // weak, my parent owns me
|
||||
nsIMenuBar * mMenuBarParent;
|
||||
|
||||
nsIDOMNode* mDOMNode; // weak ref, content model outlives us
|
||||
nsCOMPtr<nsIDOMElement> mDOMElement; // for convenience; strong ref to manage the QI
|
||||
nsIWebShell* mWebShell;
|
||||
nsIChangeManager* mManager; // weak ref, it will outlive us
|
||||
bool mConstructed;
|
||||
nsIMenu* mMenuParent; // weak, my parent owns me
|
||||
nsIMenuBar* mMenuBarParent;
|
||||
nsIChangeManager* mManager; // weak ref, it will outlive us
|
||||
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
|
||||
nsCOMPtr<nsIDOMNode> mDOMNode; //strong ref
|
||||
nsCOMPtr<nsIMenuListener> mListener;
|
||||
|
||||
bool mConstructed;
|
||||
// MacSpecific
|
||||
PRInt16 mMacMenuID;
|
||||
MenuHandle mMacMenuHandle;
|
||||
nsIMenuListener * mListener;
|
||||
UnicodeToTextRunInfo mUnicodeTextRunConverter;
|
||||
PRInt16 mHelpMenuOSItemsCount;
|
||||
PRBool mIsHelpMenu;
|
||||
PRBool mIsEnabled;
|
||||
PRBool mDestroyHandlerCalled;
|
||||
PRInt16 mMacMenuID;
|
||||
MenuHandle mMacMenuHandle;
|
||||
UnicodeToTextRunInfo mUnicodeTextRunConverter;
|
||||
PRInt16 mHelpMenuOSItemsCount;
|
||||
PRPackedBool mIsHelpMenu;
|
||||
PRPackedBool mIsEnabled;
|
||||
PRPackedBool mDestroyHandlerCalled;
|
||||
|
||||
// fetch the content node associated with the menupopup item
|
||||
void GetMenuPopupElement ( nsIDOMNode** aResult ) ;
|
||||
|
@ -146,7 +149,7 @@ protected:
|
|||
void LoadSubMenu( nsIMenu * pParentMenu, nsIDOMElement * menuElement, nsIDOMNode * menuNode);
|
||||
nsEventStatus HelpMenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
|
||||
void* menuNode, void* aWebShell);
|
||||
|
||||
|
||||
void NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& nsString);
|
||||
MenuHandle NSStringNewMenu(short menuID, nsString& menuTitle);
|
||||
MenuHandle NSStringNewChildMenu(short menuID, nsString& menuTitle);
|
||||
|
|
|
@ -64,7 +64,7 @@ typedef struct {
|
|||
|
||||
Handle gMDEF = nsnull;
|
||||
Handle gSystemMDEFHandle = nsnull;
|
||||
nsIMenuBar * gMacMenubar = nsnull;
|
||||
nsWeakPtr gMacMenubar;
|
||||
bool gFirstMenuBar = true;
|
||||
|
||||
// The four Golden Hierarchical Child Menus
|
||||
|
@ -74,7 +74,7 @@ MenuHandle gLevel4HierMenu = nsnull;
|
|||
MenuHandle gLevel5HierMenu = nsnull;
|
||||
|
||||
#if !TARGET_CARBON
|
||||
extern nsVoidArray gPreviousMenuStack;
|
||||
extern nsMenuStack gPreviousMenuStack;
|
||||
#endif
|
||||
extern PRInt16 gCurrentMenuDepth;
|
||||
|
||||
|
@ -90,7 +90,77 @@ static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
|
|||
|
||||
void InstallDefProc( short dpPath, ResType dpType, short dpID, Ptr dpAddr);
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsMenuBar, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager)
|
||||
|
||||
#if DEBUG
|
||||
nsInstanceCounter gMenuBarCounter("nsMenuBar");
|
||||
#endif
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS5(nsMenuBar, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager, nsISupportsWeakReference)
|
||||
|
||||
//
|
||||
// nsMenuBar constructor
|
||||
//
|
||||
nsMenuBar::nsMenuBar()
|
||||
{
|
||||
gCurrentMenuDepth = 1;
|
||||
|
||||
#if !TARGET_CARBON
|
||||
nsPreviousMenuStackUnwind(nsnull, nsnull);
|
||||
#endif
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenus = 0;
|
||||
mParent = nsnull;
|
||||
mIsMenuBarAdded = PR_FALSE;
|
||||
mUnicodeTextRunConverter = nsnull;
|
||||
|
||||
#if !TARGET_CARBON
|
||||
MenuDefUPP mdef = NewMenuDefProc( nsDynamicMDEFMain );
|
||||
InstallDefProc((short)nsMacResources::GetLocalResourceFile(), (ResType)'MDEF', (short)128, (Ptr) mdef );
|
||||
#endif
|
||||
|
||||
mOriginalMacMBarHandle = nsnull;
|
||||
mMacMBarHandle = nsnull;
|
||||
|
||||
mOriginalMacMBarHandle = ::GetMenuBar();
|
||||
Handle tmp = ::GetMenuBar();
|
||||
::SetMenuBar(tmp);
|
||||
this->SetNativeData((void*)tmp);
|
||||
|
||||
::ClearMenuBar();
|
||||
mRefCnt = 1; // NS_GetWeakReference does an addref then a release, so this +1 is needed
|
||||
gMacMenubar = getter_AddRefs(NS_GetWeakReference((nsIMenuBar *)this));
|
||||
mRefCnt = 0;
|
||||
// copy from nsMenu.cpp
|
||||
ScriptCode ps[1];
|
||||
ps[0] = ::GetScriptManagerVariable(smSysScript);
|
||||
|
||||
OSErr err = ::CreateUnicodeToTextRunInfoByScriptCode(0x80000000, ps, &mUnicodeTextRunConverter);
|
||||
NS_ASSERTION(err==noErr,"nsMenu::nsMenu: CreateUnicodeToTextRunInfoByScriptCode failed.");
|
||||
|
||||
#if DEBUG
|
||||
++gMenuBarCounter;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsMenuBar destructor
|
||||
//
|
||||
nsMenuBar::~nsMenuBar()
|
||||
{
|
||||
mMenusArray.Clear(); // release all menus
|
||||
|
||||
OSErr err = ::DisposeUnicodeToTextRunInfo(&mUnicodeTextRunConverter);
|
||||
NS_ASSERTION(err==noErr,"nsMenu::~nsMenu: DisposeUnicodeToTextRunInfo failed.");
|
||||
|
||||
::DisposeHandle(mMacMBarHandle);
|
||||
::DisposeHandle(mOriginalMacMBarHandle);
|
||||
|
||||
#if DEBUG
|
||||
--gMenuBarCounter;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
nsEventStatus
|
||||
|
@ -99,13 +169,16 @@ nsMenuBar::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
|||
// Dispatch menu event
|
||||
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
||||
|
||||
for (int i = mMenuVoidArray.Count(); i > 0; --i)
|
||||
PRUint32 numItems;
|
||||
mMenusArray.Count(&numItems);
|
||||
|
||||
for (PRUint32 i = numItems; i > 0; --i)
|
||||
{
|
||||
nsIMenuListener * menuListener = nsnull;
|
||||
((nsISupports*)mMenuVoidArray[i-1])->QueryInterface(NS_GET_IID(nsIMenuListener), (void**)&menuListener);
|
||||
if(menuListener){
|
||||
nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenusArray.ElementAt(i - 1));
|
||||
nsCOMPtr<nsIMenuListener> menuListener = do_QueryInterface(menuSupports);
|
||||
if(menuListener)
|
||||
{
|
||||
eventStatus = menuListener->MenuItemSelected(aMenuEvent);
|
||||
NS_RELEASE(menuListener);
|
||||
if(nsEventStatus_eIgnore != eventStatus)
|
||||
return eventStatus;
|
||||
}
|
||||
|
@ -120,32 +193,36 @@ nsMenuBar::MenuSelected(const nsMenuEvent & aMenuEvent)
|
|||
// Dispatch event
|
||||
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
||||
|
||||
nsIMenuListener * menuListener = nsnull;
|
||||
nsCOMPtr<nsIMenuListener> menuListener;
|
||||
//((nsISupports*)mMenuVoidArray[i-1])->QueryInterface(NS_GET_IID(nsIMenuListener), (void**)&menuListener);
|
||||
//printf("gPreviousMenuStack.Count() = %d \n", gPreviousMenuStack.Count());
|
||||
#if !TARGET_CARBON
|
||||
if (gPreviousMenuStack[gPreviousMenuStack.Count() - 1])
|
||||
((nsIMenu*)gPreviousMenuStack[gPreviousMenuStack.Count() - 1])->QueryInterface(NS_GET_IID(nsIMenuListener), (void**)&menuListener);
|
||||
nsCOMPtr<nsIMenu> theMenu;
|
||||
gPreviousMenuStack.GetMenuAt(gPreviousMenuStack.Count() - 1, getter_AddRefs(theMenu));
|
||||
menuListener = do_QueryInterface(theMenu);
|
||||
#endif
|
||||
if (menuListener) {
|
||||
//TODO: MenuSelected is the right thing to call...
|
||||
//eventStatus = menuListener->MenuSelected(aMenuEvent);
|
||||
eventStatus = menuListener->MenuItemSelected(aMenuEvent);
|
||||
NS_RELEASE(menuListener);
|
||||
if (nsEventStatus_eIgnore != eventStatus)
|
||||
return eventStatus;
|
||||
} else {
|
||||
// If it's the help menu, gPreviousMenuStack won't be accurate so we need to get the listener a different way
|
||||
// We'll do it the old fashioned way of looping through and finding it
|
||||
for (int i = mMenuVoidArray.Count(); i > 0; --i) {
|
||||
((nsISupports*)mMenuVoidArray[i-1])->QueryInterface(NS_GET_IID(nsIMenuListener), (void**)&menuListener);
|
||||
if (menuListener) {
|
||||
PRUint32 numItems;
|
||||
mMenusArray.Count(&numItems);
|
||||
for (PRUint32 i = numItems; i > 0; --i)
|
||||
{
|
||||
nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenusArray.ElementAt(i - 1));
|
||||
nsCOMPtr<nsIMenuListener> thisListener = do_QueryInterface(menuSupports);
|
||||
if (thisListener)
|
||||
{
|
||||
//TODO: MenuSelected is the right thing to call...
|
||||
//eventStatus = menuListener->MenuSelected(aMenuEvent);
|
||||
eventStatus = menuListener->MenuItemSelected(aMenuEvent);
|
||||
NS_RELEASE(menuListener);
|
||||
if(nsEventStatus_eIgnore != eventStatus)
|
||||
return eventStatus;
|
||||
//eventStatus = menuListener->MenuSelected(aMenuEvent);
|
||||
eventStatus = thisListener->MenuItemSelected(aMenuEvent);
|
||||
if(nsEventStatus_eIgnore != eventStatus)
|
||||
return eventStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -194,13 +271,9 @@ nsEventStatus
|
|||
nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
|
||||
void * menubarNode, void * aWebShell )
|
||||
{
|
||||
mWebShell = (nsIWebShell*) aWebShell;
|
||||
NS_ADDREF(mWebShell);
|
||||
mDOMNode = (nsIDOMNode*)menubarNode;
|
||||
NS_ADDREF(mDOMNode);
|
||||
|
||||
nsIMenuBar * pnsMenuBar = this;
|
||||
|
||||
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(NS_STATIC_CAST(nsIWebShell*, aWebShell)));
|
||||
mDOMNode = NS_STATIC_CAST(nsIDOMNode*, menubarNode); // strong ref
|
||||
|
||||
if(gFirstMenuBar) {
|
||||
gFirstMenuBar = false;
|
||||
// Add the 4 Golden Hierarchical Menus to the MenuList
|
||||
|
@ -271,24 +344,25 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
|
|||
::InsertMenu(gLevel5HierMenu, hierMenu);
|
||||
}
|
||||
|
||||
pnsMenuBar->Create(aParentWindow);
|
||||
RegisterAsDocumentObserver ( mWebShell );
|
||||
Create(aParentWindow);
|
||||
|
||||
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
|
||||
if (webShell)
|
||||
RegisterAsDocumentObserver(webShell);
|
||||
|
||||
// set pnsMenuBar as a nsMenuListener on aParentWindow
|
||||
nsCOMPtr<nsIMenuListener> menuListener;
|
||||
pnsMenuBar->QueryInterface(NS_GET_IID(nsIMenuListener), getter_AddRefs(menuListener));
|
||||
aParentWindow->AddMenuListener(menuListener);
|
||||
// set this as a nsMenuListener on aParentWindow
|
||||
aParentWindow->AddMenuListener((nsIMenuListener *)this);
|
||||
|
||||
nsIDOMNode * menuNode = nsnull;
|
||||
((nsIDOMNode*)menubarNode)->GetFirstChild(&menuNode);
|
||||
while (menuNode) {
|
||||
NS_ADDREF(menuNode);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> menuNode;
|
||||
mDOMNode->GetFirstChild(getter_AddRefs(menuNode));
|
||||
while (menuNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
|
||||
if (menuElement) {
|
||||
nsString menuNodeType;
|
||||
nsString menuName;
|
||||
nsString menuAccessKey; menuAccessKey.AssignWithConversion(" ");
|
||||
if (menuElement)
|
||||
{
|
||||
nsAutoString menuNodeType;
|
||||
nsAutoString menuName;
|
||||
nsAutoString menuAccessKey; menuAccessKey.AssignWithConversion(" ");
|
||||
|
||||
menuElement->GetNodeName(menuNodeType);
|
||||
if (menuNodeType.EqualsWithConversion("menu")) {
|
||||
|
@ -299,16 +373,16 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
|
|||
|
||||
// Create nsMenu, the menubar will own it
|
||||
nsCOMPtr<nsIMenu> pnsMenu ( do_CreateInstance(kMenuCID) );
|
||||
if ( pnsMenu ) {
|
||||
nsCOMPtr<nsISupports> supports ( do_QueryInterface(pnsMenuBar) );
|
||||
nsCOMPtr<nsIChangeManager> manager ( do_QueryInterface(NS_STATIC_CAST(nsIMenuBar*,this)) );
|
||||
pnsMenu->Create(supports, menuName, menuAccessKey, manager,
|
||||
NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menuNode);
|
||||
if ( pnsMenu )
|
||||
{
|
||||
pnsMenu->Create(NS_STATIC_CAST(nsIMenuBar*, this), menuName, menuAccessKey,
|
||||
NS_STATIC_CAST(nsIChangeManager *, this),
|
||||
NS_REINTERPRET_CAST(nsIWebShell*, aWebShell), menuNode);
|
||||
|
||||
// Make nsMenu a child of nsMenuBar. nsMenuBar takes ownership
|
||||
pnsMenuBar->AddMenu(pnsMenu);
|
||||
AddMenu(pnsMenu);
|
||||
|
||||
nsString menuIDstring;
|
||||
nsAutoString menuIDstring;
|
||||
menuElement->GetAttribute(NS_ConvertASCIItoUCS2("id"), menuIDstring);
|
||||
if(menuIDstring.EqualsWithConversion("menu_Help")) {
|
||||
nsMenuEvent event;
|
||||
|
@ -323,17 +397,17 @@ nsMenuBar::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWind
|
|||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> oldmenuNode(do_QueryInterface(menuNode));
|
||||
oldmenuNode->GetNextSibling(&menuNode);
|
||||
nsCOMPtr<nsIDOMNode> tempNode = menuNode;
|
||||
tempNode->GetNextSibling(getter_AddRefs(menuNode));
|
||||
} // end while (nsnull != menuNode)
|
||||
|
||||
// Give the aParentWindow this nsMenuBar to hold onto.
|
||||
// The parent takes ownership
|
||||
aParentWindow->SetMenuBar(pnsMenuBar);
|
||||
aParentWindow->SetMenuBar(this);
|
||||
|
||||
#ifdef XP_MAC
|
||||
Handle tempMenuBar = ::GetMenuBar(); // Get a copy of the menu list
|
||||
pnsMenuBar->SetNativeData((void*)tempMenuBar);
|
||||
SetNativeData((void*)tempMenuBar);
|
||||
#endif
|
||||
|
||||
return nsEventStatus_eIgnore;
|
||||
|
@ -347,67 +421,6 @@ nsMenuBar::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
// nsMenuBar constructor
|
||||
//
|
||||
nsMenuBar :: nsMenuBar()
|
||||
{
|
||||
gCurrentMenuDepth = 1;
|
||||
#if !TARGET_CARBON
|
||||
nsPreviousMenuStackUnwind(nsnull, nsnull);
|
||||
#endif
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenus = 0;
|
||||
mParent = nsnull;
|
||||
mIsMenuBarAdded = PR_FALSE;
|
||||
mWebShell = nsnull;
|
||||
mDOMNode = nsnull;
|
||||
|
||||
#if !TARGET_CARBON
|
||||
MenuDefUPP mdef = NewMenuDefProc( nsDynamicMDEFMain );
|
||||
InstallDefProc((short)nsMacResources::GetLocalResourceFile(), (ResType)'MDEF', (short)128, (Ptr) mdef );
|
||||
#endif
|
||||
|
||||
mOriginalMacMBarHandle = nsnull;
|
||||
mMacMBarHandle = nsnull;
|
||||
|
||||
mOriginalMacMBarHandle = ::GetMenuBar();
|
||||
Handle tmp = ::GetMenuBar();
|
||||
::SetMenuBar(tmp);
|
||||
this->SetNativeData((void*)tmp);
|
||||
|
||||
::ClearMenuBar();
|
||||
gMacMenubar = this;
|
||||
// copy from nsMenu.cpp
|
||||
ScriptCode ps[1];
|
||||
ps[0] = ::GetScriptManagerVariable(smSysScript);
|
||||
|
||||
OSErr err = ::CreateUnicodeToTextRunInfoByScriptCode(0x80000000,ps,&mUnicodeTextRunConverter);
|
||||
NS_ASSERTION(err==noErr,"nsMenu::nsMenu: CreateUnicodeToTextRunInfoByScriptCode failed.");
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsMenuBar destructor
|
||||
//
|
||||
nsMenuBar :: ~nsMenuBar()
|
||||
{
|
||||
//NS_IF_RELEASE(mParent);
|
||||
|
||||
while(mNumMenus)
|
||||
{
|
||||
--mNumMenus;
|
||||
nsISupports* menu = (nsISupports*)mMenuVoidArray[mNumMenus];
|
||||
NS_IF_RELEASE( menu );
|
||||
}
|
||||
OSErr err = ::DisposeUnicodeToTextRunInfo(&mUnicodeTextRunConverter);
|
||||
NS_ASSERTION(err==noErr,"nsMenu::~nsMenu: DisposeUnicodeToTextRunInfo failed.");
|
||||
|
||||
::DisposeHandle(mMacMBarHandle);
|
||||
::DisposeHandle(mOriginalMacMBarHandle);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Create the proper widget
|
||||
|
@ -416,15 +429,13 @@ nsMenuBar :: ~nsMenuBar()
|
|||
NS_METHOD nsMenuBar::Create(nsIWidget *aParent)
|
||||
{
|
||||
SetParent(aParent);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetParent(nsIWidget *&aParent)
|
||||
{
|
||||
aParent = mParent;
|
||||
|
||||
NS_IF_ADDREF(aParent = mParent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -432,8 +443,7 @@ NS_METHOD nsMenuBar::GetParent(nsIWidget *&aParent)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::SetParent(nsIWidget *aParent)
|
||||
{
|
||||
mParent = aParent;
|
||||
|
||||
mParent = aParent; // weak ref
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -441,11 +451,9 @@ NS_METHOD nsMenuBar::SetParent(nsIWidget *aParent)
|
|||
NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
|
||||
{
|
||||
// XXX add to internal data structure
|
||||
nsISupports * supports = nsnull;
|
||||
aMenu->QueryInterface(NS_GET_IID(nsISupports), (void**)&supports);
|
||||
if(supports){
|
||||
mMenuVoidArray.AppendElement( supports );
|
||||
}
|
||||
nsCOMPtr<nsISupports> supports = do_QueryInterface(aMenu);
|
||||
if(supports)
|
||||
mMenusArray.AppendElement(supports); // owner
|
||||
|
||||
#ifdef APPLE_MENU_HACK
|
||||
if (mNumMenus == 0)
|
||||
|
@ -456,35 +464,25 @@ NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
|
|||
if (appleMenu)
|
||||
{
|
||||
nsresult ret;
|
||||
nsIStringBundleService *pStringService = nsnull;
|
||||
ret = nsServiceManager::GetService(kStringBundleServiceCID,
|
||||
kIStringBundleServiceIID, (nsISupports**) &pStringService);
|
||||
nsCOMPtr<nsIStringBundleService> pStringService = do_GetService(kStringBundleServiceCID, &ret);
|
||||
if (NS_FAILED(ret)) {
|
||||
NS_WARNING("cannot get string service\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//XXX "chrome://global/locale/brand.properties" should be less hardcoded
|
||||
nsILocale *locale = nsnull;
|
||||
nsIStringBundle *bundle = nsnull;
|
||||
ret = pStringService->CreateBundle("chrome://global/locale/brand.properties",
|
||||
locale, &bundle);
|
||||
|
||||
nsServiceManager::ReleaseService(kStringBundleServiceCID, pStringService);
|
||||
|
||||
nsCOMPtr<nsIStringBundle> bundle;
|
||||
ret = pStringService->CreateBundle("chrome://global/locale/brand.properties", nsnull, getter_AddRefs(bundle));
|
||||
if (NS_FAILED(ret)) {
|
||||
NS_WARNING("cannot create instance\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
//XXX "aboutStrName" should be less hardcoded
|
||||
nsAutoString temp; temp.AssignWithConversion("aboutStrName");
|
||||
const PRUnichar *ptrtmp = temp.GetUnicode();
|
||||
PRUnichar *ptrv = nsnull;
|
||||
bundle->GetStringFromName(ptrtmp, &ptrv);
|
||||
|
||||
bundle->GetStringFromName(NS_ConvertASCIItoUCS2("aboutStrName").GetUnicode(), &ptrv);
|
||||
nsAutoString label = ptrv;
|
||||
|
||||
nsCRT::free(ptrv);
|
||||
|
||||
::AppendMenu(appleMenu, "\pa");
|
||||
NSStringSetMenuItemText(appleMenu, 1, label);
|
||||
|
@ -502,10 +500,10 @@ NS_METHOD nsMenuBar::AddMenu(nsIMenu * aMenu)
|
|||
PRBool helpMenu;
|
||||
aMenu->IsHelpMenu(&helpMenu);
|
||||
if(!helpMenu) {
|
||||
nsString menuHidden; menuHidden.AssignWithConversion(" ");
|
||||
nsCOMPtr<nsIDOMNode> domNode;
|
||||
aMenu->GetDOMNode(getter_AddRefs(domNode));
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(domNode);
|
||||
nsAutoString menuHidden;
|
||||
domElement->GetAttribute(NS_ConvertASCIItoUCS2("hidden"), menuHidden);
|
||||
if(! menuHidden.EqualsWithConversion("true"))
|
||||
::InsertMenu(menuHandle, 0);
|
||||
|
@ -578,17 +576,11 @@ NS_METHOD nsMenuBar::GetMenuCount(PRUint32 &aCount)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
|
||||
{
|
||||
nsISupports * supports = nsnull;
|
||||
supports = (nsISupports*) mMenuVoidArray.ElementAt(aCount);
|
||||
if(!supports) {
|
||||
return NS_OK;
|
||||
}
|
||||
aMenu = NULL;
|
||||
nsCOMPtr<nsISupports> supports = getter_AddRefs(mMenusArray.ElementAt(aCount));
|
||||
if (!supports) return NS_OK;
|
||||
|
||||
nsIMenu * menu = nsnull;
|
||||
supports->QueryInterface(NS_GET_IID(nsISupports), (void**)&menu);
|
||||
aMenu = menu;
|
||||
|
||||
return NS_OK;
|
||||
return CallQueryInterface(supports, &aMenu); // addref
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -600,11 +592,7 @@ NS_METHOD nsMenuBar::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::RemoveMenu(const PRUint32 aCount)
|
||||
{
|
||||
nsISupports* menu = (nsISupports*)mMenuVoidArray[aCount];
|
||||
NS_IF_RELEASE( menu );
|
||||
|
||||
mMenuVoidArray.RemoveElementAt(aCount);
|
||||
|
||||
mMenusArray.RemoveElementAt(aCount);
|
||||
::DrawMenuBar();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -612,6 +600,8 @@ NS_METHOD nsMenuBar::RemoveMenu(const PRUint32 aCount)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::RemoveAll()
|
||||
{
|
||||
NS_ASSERTION(0, "Not implemented!");
|
||||
// mMenusArray.Clear(); // maybe?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -633,22 +623,30 @@ NS_METHOD nsMenuBar::SetNativeData(void* aData)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuBar::Paint()
|
||||
{
|
||||
gMacMenubar = this;
|
||||
PRBool isHelpMenu;
|
||||
gMacMenubar = getter_AddRefs(NS_GetWeakReference((nsIMenuBar *)this));
|
||||
|
||||
::SetMenuBar(mMacMBarHandle);
|
||||
// Now we have blown away the merged Help menu, so we have to rebuild it
|
||||
for(int i = mMenuVoidArray.Count()-1; i>=0; --i) {
|
||||
((nsIMenu*)mMenuVoidArray[i])->IsHelpMenu(&isHelpMenu);
|
||||
if(isHelpMenu){
|
||||
PRUint32 numItems;
|
||||
mMenusArray.Count(&numItems);
|
||||
|
||||
for (PRInt32 i = numItems - 1; i >= 0; --i)
|
||||
{
|
||||
nsCOMPtr<nsISupports> thisItem = getter_AddRefs(mMenusArray.ElementAt(i));
|
||||
nsCOMPtr<nsIMenu> menu = do_QueryInterface(thisItem);
|
||||
PRBool isHelpMenu = PR_FALSE;
|
||||
if (menu)
|
||||
menu->IsHelpMenu(&isHelpMenu);
|
||||
if (isHelpMenu)
|
||||
{
|
||||
MenuHandle helpMenuHandle;
|
||||
#if !TARGET_CARBON
|
||||
::HMGetHelpMenuHandle(&helpMenuHandle);
|
||||
((nsIMenu*)mMenuVoidArray[i])->SetNativeData((void*)helpMenuHandle);
|
||||
menu->SetNativeData((void*)helpMenuHandle);
|
||||
#endif
|
||||
nsMenuEvent event;
|
||||
event.mCommand = (unsigned int) helpMenuHandle;
|
||||
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface((nsIMenu*)mMenuVoidArray[i]));
|
||||
nsCOMPtr<nsIMenuListener> listener = do_QueryInterface(menu);
|
||||
listener->MenuSelected(event);
|
||||
}
|
||||
}
|
||||
|
@ -673,9 +671,14 @@ void InstallDefProc(
|
|||
gMDEF = (Handle) jH;
|
||||
UseResFile(savePath);
|
||||
|
||||
if (!jH) /* is there no defproc resource? */
|
||||
if (!jH) /* is there no defproc resource? */\
|
||||
{
|
||||
#if DEBUG
|
||||
DebugStr("\pStub Defproc Not Found!");
|
||||
|
||||
#endif
|
||||
ExitToShell(); // bail
|
||||
}
|
||||
|
||||
HNoPurge((Handle)jH); /* make this resource nonpurgeable */
|
||||
(**jH).jmpAddr = dpAddr;
|
||||
(**jH).jmpInstr = 0x4EF9;
|
||||
|
|
|
@ -27,13 +27,15 @@
|
|||
#include "nsIMenuListener.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIChangeManager.h"
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#include "Types.h"
|
||||
#include <MacTypes.h>
|
||||
#include <UnicodeConverter.h>
|
||||
|
||||
extern nsIMenuBar * gMacMenubar;
|
||||
extern nsWeakPtr gMacMenubar;
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
|
@ -41,8 +43,11 @@ class nsIWidget;
|
|||
* Native Mac MenuBar wrapper
|
||||
*/
|
||||
|
||||
class nsMenuBar : public nsIMenuBar, public nsIMenuListener, public nsIDocumentObserver,
|
||||
public nsIChangeManager
|
||||
class nsMenuBar : public nsIMenuBar,
|
||||
public nsIMenuListener,
|
||||
public nsIDocumentObserver,
|
||||
public nsIChangeManager,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -130,16 +135,17 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
nsHashtable mObserverTable; // stores observers for content change notification
|
||||
nsHashtable mObserverTable; // stores observers for content change notification
|
||||
|
||||
PRUint32 mNumMenus;
|
||||
nsVoidArray mMenuVoidArray;
|
||||
nsIWidget * mParent;
|
||||
PRUint32 mNumMenus;
|
||||
nsSupportsArray mMenusArray; // holds refs
|
||||
nsCOMPtr<nsIDOMNode> mDOMNode;
|
||||
nsIWidget * mParent; // weak ref
|
||||
|
||||
PRBool mIsMenuBarAdded;
|
||||
PRBool mIsMenuBarAdded;
|
||||
|
||||
nsIWebShell * mWebShell;
|
||||
nsIDOMNode * mDOMNode;
|
||||
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
|
||||
|
||||
|
||||
void RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) ;
|
||||
|
||||
|
@ -148,7 +154,7 @@ protected:
|
|||
Handle mOriginalMacMBarHandle;
|
||||
UnicodeToTextRunInfo mUnicodeTextRunConverter;
|
||||
void NSStringSetMenuItemText(MenuHandle macMenuHandle, short menuItem, nsString& nsString);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // nsMenuBar_h__
|
||||
|
|
|
@ -31,11 +31,17 @@
|
|||
#include "nsIMenuBar.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsDynamicMDEF.h"
|
||||
|
||||
#include "nsStringUtil.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsMenuItem, nsIMenuItem, nsIMenuListener, nsIChangeObserver)
|
||||
|
||||
#if DEBUG
|
||||
nsInstanceCounter gMenuItemCounter("nsMenuItem");
|
||||
#endif
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS4(nsMenuItem, nsIMenuItem, nsIMenuListener, nsIChangeObserver, nsISupportsWeakReference)
|
||||
|
||||
//
|
||||
// nsMenuItem constructor
|
||||
|
@ -44,14 +50,15 @@ nsMenuItem::nsMenuItem()
|
|||
{
|
||||
NS_INIT_REFCNT();
|
||||
mMenuParent = nsnull;
|
||||
mTarget = nsnull;
|
||||
mIsSeparator = PR_FALSE;
|
||||
mWebShell = nsnull;
|
||||
mDOMNode = nsnull;
|
||||
mKeyEquivalent.AssignWithConversion(" ");
|
||||
mEnabled = PR_TRUE;
|
||||
mIsChecked = PR_FALSE;
|
||||
mMenuType = eRegular;
|
||||
|
||||
#if DEBUG
|
||||
++gMenuItemCounter;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -60,14 +67,16 @@ nsMenuItem::nsMenuItem()
|
|||
nsMenuItem::~nsMenuItem()
|
||||
{
|
||||
//printf("nsMenuItem::~nsMenuItem() called \n");
|
||||
NS_IF_RELEASE(mTarget);
|
||||
|
||||
// if we're a radio menu, we've been registered to get AttributeChanged, so
|
||||
// make sure we unregister when we go away.
|
||||
if ( mMenuType == eRadio ) {
|
||||
nsCOMPtr<nsIContent> content ( do_QueryInterface(mDOMNode) );
|
||||
mManager->Unregister ( content );
|
||||
if (mMenuType == eRadio) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
|
||||
mManager->Unregister(content);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
--gMenuItemCounter;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,10 +84,9 @@ NS_METHOD nsMenuItem::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool
|
|||
EMenuItemType aItemType, PRBool aEnabled,
|
||||
nsIChangeManager* aManager, nsIWebShell* aShell, nsIDOMNode* aNode )
|
||||
{
|
||||
mDOMNode = aNode;
|
||||
mDOMElement = do_QueryInterface ( aNode );
|
||||
mMenuParent = aParent;
|
||||
mWebShell = aShell;
|
||||
mDOMNode = aNode; // addref
|
||||
mMenuParent = aParent; // weak
|
||||
mWebShellWeakRef = getter_AddRefs(NS_GetWeakReference(aShell));
|
||||
|
||||
mEnabled = aEnabled;
|
||||
mMenuType = aItemType;
|
||||
|
@ -86,9 +94,9 @@ NS_METHOD nsMenuItem::Create ( nsIMenu* aParent, const nsString & aLabel, PRBool
|
|||
// if we're a radio menu, register for AttributeChanged messages
|
||||
mManager = aManager;
|
||||
if ( aItemType == eRadio ) {
|
||||
nsCOMPtr<nsIContent> content ( do_QueryInterface(mDOMNode) );
|
||||
nsCOMPtr<nsIChangeObserver> obs ( do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this)) );
|
||||
mManager->Register ( content, obs );
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mDOMNode);
|
||||
nsCOMPtr<nsIChangeObserver> obs = do_QueryInterface(NS_STATIC_CAST(nsIChangeObserver*,this));
|
||||
mManager->Register(content, obs); // does not addref this
|
||||
}
|
||||
|
||||
mIsSeparator = aIsSeparator;
|
||||
|
@ -117,14 +125,12 @@ NS_METHOD nsMenuItem::SetChecked(PRBool aIsEnabled)
|
|||
mIsChecked = aIsEnabled;
|
||||
|
||||
// update the content model
|
||||
if ( mIsChecked )
|
||||
mDOMElement->SetAttribute(NS_ConvertASCIItoUCS2("checked"), NS_ConvertASCIItoUCS2("true"));
|
||||
else
|
||||
mDOMElement->SetAttribute(NS_ConvertASCIItoUCS2("checked"), NS_ConvertASCIItoUCS2("false"));
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
domElement->SetAttribute(NS_ConvertASCIItoUCS2("checked"), NS_ConvertASCIItoUCS2(mIsChecked ? "true" : "false"));
|
||||
|
||||
// uncheck others if we're a radiomenu
|
||||
if ( mMenuType == eRadio && aIsEnabled )
|
||||
UncheckRadioSiblings ( mDOMElement );
|
||||
UncheckRadioSiblings (domElement);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -148,7 +154,7 @@ NS_METHOD nsMenuItem::GetMenuItemType(EMenuItemType *aType)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetTarget(nsIWidget *& aTarget)
|
||||
{
|
||||
aTarget = mTarget;
|
||||
NS_IF_ADDREF(aTarget = mTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -162,13 +168,15 @@ NS_METHOD nsMenuItem::GetNativeData(void *& aData)
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::AddMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
mXULCommandListener = aMenuListener;
|
||||
return NS_OK;
|
||||
mXULCommandListener = aMenuListener; // addref
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
{
|
||||
if (mXULCommandListener.get() == aMenuListener)
|
||||
mXULCommandListener = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -212,11 +220,11 @@ nsEventStatus nsMenuItem::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
|||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
//if(mXULCommandListener)
|
||||
// return mXULCommandListener->MenuSelected(aMenuEvent);
|
||||
|
||||
//if(mXULCommandListener)
|
||||
// return mXULCommandListener->MenuSelected(aMenuEvent);
|
||||
|
||||
DoCommand();
|
||||
return nsEventStatus_eIgnore;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -224,7 +232,7 @@ nsEventStatus nsMenuItem::MenuSelected(const nsMenuEvent & aMenuEvent)
|
|||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuDeselected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -232,15 +240,15 @@ nsEventStatus nsMenuItem::MenuConstruct(
|
|||
const nsMenuEvent & aMenuEvent,
|
||||
nsIWidget * aParentWindow,
|
||||
void * menuNode,
|
||||
void * aWebShell)
|
||||
void * aWebShell)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItem::MenuDestruct(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
return nsEventStatus_eIgnore;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
|
||||
|
@ -254,21 +262,20 @@ NS_METHOD nsMenuItem::DoCommand()
|
|||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
MenuHelpers::WebShellToPresContext ( mWebShell, getter_AddRefs(presContext) );
|
||||
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
|
||||
if (!webShell)
|
||||
{
|
||||
NS_ERROR("No web shell");
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
MenuHelpers::WebShellToPresContext(webShell, getter_AddRefs(presContext));
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsMouseEvent event;
|
||||
event.eventStructType = NS_MOUSE_EVENT;
|
||||
event.message = NS_MENU_ACTION;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
|
||||
if(!element) {
|
||||
NS_ERROR("Unable to QI dom element.");
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> contentNode;
|
||||
contentNode = do_QueryInterface(element);
|
||||
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(mDOMNode);
|
||||
if (!contentNode) {
|
||||
NS_ERROR("DOM Node doesn't support the nsIContent interface required to handle DOM events.");
|
||||
return rv;
|
||||
|
@ -284,9 +291,9 @@ NS_METHOD nsMenuItem::DoCommand()
|
|||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuItem::GetModifiers(PRUint8 * aModifiers)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
*aModifiers = mModifiers;
|
||||
return res;
|
||||
nsresult res = NS_OK;
|
||||
*aModifiers = mModifiers;
|
||||
return res;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -321,16 +328,16 @@ NS_METHOD nsMenuItem::GetShortcutChar(nsString &aText)
|
|||
// uncheck them all.
|
||||
//
|
||||
void
|
||||
nsMenuItem :: UncheckRadioSiblings ( nsIDOMElement* inCheckedElement )
|
||||
nsMenuItem :: UncheckRadioSiblings(nsIDOMElement* inCheckedElement)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> checkedNode ( do_QueryInterface(inCheckedElement) );
|
||||
nsCOMPtr<nsIDOMNode> checkedNode = do_QueryInterface(inCheckedElement);
|
||||
|
||||
nsAutoString myGroupName;
|
||||
inCheckedElement->GetAttribute(NS_ConvertASCIItoUCS2("name"), myGroupName);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
checkedNode->GetParentNode(getter_AddRefs(parent));
|
||||
if ( !parent )
|
||||
if (!parent )
|
||||
return;
|
||||
nsCOMPtr<nsIDOMNode> currSibling;
|
||||
parent->GetFirstChild(getter_AddRefs(currSibling));
|
||||
|
@ -352,7 +359,6 @@ nsMenuItem :: UncheckRadioSiblings ( nsIDOMElement* inCheckedElement )
|
|||
nsIDOMNode* next;
|
||||
currSibling->GetNextSibling(&next);
|
||||
currSibling = dont_AddRef(next);
|
||||
|
||||
} // for each sibling
|
||||
|
||||
} // UncheckRadioSiblings
|
||||
|
@ -369,11 +375,13 @@ nsMenuItem :: AttributeChanged ( nsIDocument *aDocument, PRInt32 aNameSpaceID, n
|
|||
PRInt32 aHint)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> checkedAtom = NS_NewAtom("checked");
|
||||
nsAutoString checked;
|
||||
if ( aAttribute == checkedAtom.get() ) {
|
||||
mDOMElement->GetAttribute(NS_ConvertASCIItoUCS2("checked"), checked);
|
||||
if ( checked.EqualsWithConversion("true") )
|
||||
UncheckRadioSiblings ( mDOMElement );
|
||||
if (aAttribute == checkedAtom.get())
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(mDOMNode);
|
||||
nsAutoString checked;
|
||||
domElement->GetAttribute(NS_ConvertASCIItoUCS2("checked"), checked);
|
||||
if (checked.EqualsWithConversion("true"))
|
||||
UncheckRadioSiblings(domElement);
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "nsString.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsIChangeManager.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
|
||||
class nsIMenu;
|
||||
|
@ -37,7 +38,10 @@ class nsIWidget;
|
|||
* Native Motif MenuItem wrapper
|
||||
*/
|
||||
|
||||
class nsMenuItem : public nsIMenuItem, public nsIMenuListener, public nsIChangeObserver
|
||||
class nsMenuItem : public nsIMenuItem,
|
||||
public nsIMenuListener,
|
||||
public nsIChangeObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
nsMenuItem();
|
||||
|
@ -80,24 +84,22 @@ protected:
|
|||
|
||||
void UncheckRadioSiblings ( nsIDOMElement* inCheckedElement ) ;
|
||||
|
||||
nsAutoString mLabel;
|
||||
nsAutoString mKeyEquivalent;
|
||||
nsString mLabel;
|
||||
nsString mKeyEquivalent;
|
||||
|
||||
nsIMenu * mMenuParent; // weak, parent owns us
|
||||
nsIWidget * mTarget;
|
||||
nsIMenu* mMenuParent; // weak, parent owns us
|
||||
nsIChangeManager* mManager; // weak
|
||||
|
||||
nsCOMPtr<nsIWidget> mTarget; // never set?
|
||||
nsCOMPtr<nsIMenuListener> mXULCommandListener;
|
||||
PRBool mIsSeparator;
|
||||
nsIMenuListener * mListener;
|
||||
|
||||
nsIWebShell* mWebShell; // weak, document outlives us
|
||||
nsCOMPtr<nsIDOMElement> mDOMElement; // for convenience; strong to manage QI
|
||||
nsIDOMNode* mDOMNode; // weak, content outlives us
|
||||
nsIChangeManager* mManager; // weak, manager outlives us
|
||||
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
|
||||
nsCOMPtr<nsIDOMNode> mDOMNode;
|
||||
|
||||
PRUint8 mModifiers;
|
||||
PRBool mEnabled;
|
||||
PRBool mIsChecked;
|
||||
PRPackedBool mIsSeparator;
|
||||
PRPackedBool mEnabled;
|
||||
PRPackedBool mIsChecked;
|
||||
EMenuItemType mMenuType;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче