mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
rewrite osx menus to use carbon command events to work around all MenuSelect problems on carbon on 9. r=beard/sr=sfraser, bug#58227
This commit is contained in:
parent
ab90544f95
commit
96d12a2ec0
@ -24,3 +24,8 @@
|
||||
#define _IMPL_NS_WIDGET 1
|
||||
|
||||
#include "WidgetDebug.prefix"
|
||||
|
||||
#if !TARGET_CARBON
|
||||
#define USE_MENUSELECT 1
|
||||
#endif
|
||||
|
||||
|
@ -24,3 +24,7 @@
|
||||
#define _IMPL_NS_WIDGET 1
|
||||
|
||||
#include "Widget.prefix"
|
||||
|
||||
#if !TARGET_CARBON
|
||||
#define USE_MENUSELECT 1
|
||||
#endif
|
||||
|
@ -48,6 +48,8 @@ class nsIMenuItem;
|
||||
class nsIMenuListener;
|
||||
class nsIChangeManager;
|
||||
class nsIContent;
|
||||
class nsIMenuCommandDispatcher;
|
||||
|
||||
|
||||
// {ab6cea83-00ff-11d5-bb6f-f432a43ead7c}
|
||||
#define NS_IMENU_IID \
|
||||
|
@ -5,3 +5,4 @@
|
||||
nsMacMessageSink.h
|
||||
nsMacMessagePump.h
|
||||
nsIChangeManager.idl
|
||||
nsIMenuCommandDispatcher.idl
|
||||
|
@ -89,6 +89,7 @@ CPPSRCS = nsAppShell.cpp \
|
||||
|
||||
XPIDLSRCS += \
|
||||
nsIChangeManager.idl \
|
||||
nsIMenuCommandDispatcher.idl \
|
||||
$(NULL)
|
||||
|
||||
GARBAGE += $(GFX_LCPPSRCS)
|
||||
|
@ -528,6 +528,8 @@ PRBool nsMacEventHandler::HandleOSEvent ( EventRecord& aOSEvent )
|
||||
}
|
||||
|
||||
|
||||
#if USE_MENUSELECT
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Handle Menu commands
|
||||
@ -592,6 +594,7 @@ PRBool nsMacEventHandler::HandleMenuCommand(
|
||||
return eventHandled;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -138,7 +138,9 @@ public:
|
||||
virtual ~nsMacEventHandler();
|
||||
|
||||
virtual PRBool HandleOSEvent(EventRecord& aOSEvent);
|
||||
#if USE_MENUSELECT
|
||||
virtual PRBool HandleMenuCommand(EventRecord& aOSEvent, long aMenuResult);
|
||||
#endif
|
||||
|
||||
// Tell Gecko that a drag event has occurred and should go into Gecko
|
||||
virtual PRBool DragEvent ( unsigned int aMessage, Point aMouseGlobal, UInt16 aKeyModifiers ) ;
|
||||
|
@ -540,11 +540,13 @@ void nsMacMessagePump::DoMouseDown(EventRecord &anEvent)
|
||||
nsWatchTask::GetTask().Suspend();
|
||||
long menuResult = ::MenuSelect(anEvent.where);
|
||||
nsWatchTask::GetTask().Resume();
|
||||
#if USE_MENUSELECT
|
||||
if (HiWord(menuResult) != 0)
|
||||
{
|
||||
menuResult = ConvertOSMenuResultToPPMenuResult(menuResult);
|
||||
DoMenu(anEvent, menuResult);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
@ -798,6 +800,7 @@ void nsMacMessagePump::DoKey(EventRecord &anEvent)
|
||||
//}
|
||||
//else
|
||||
{
|
||||
#if USE_MENUSELECT
|
||||
PRBool handled = DispatchOSEventToRaptor(anEvent, GetFrontApplicationWindow());
|
||||
/* we want to call this if cmdKey is pressed and no other modifier keys are pressed */
|
||||
if((!handled) && (anEvent.what == keyDown) && (anEvent.modifiers == cmdKey) )
|
||||
@ -810,6 +813,7 @@ void nsMacMessagePump::DoKey(EventRecord &anEvent)
|
||||
DoMenu(anEvent, menuResult);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -841,13 +845,13 @@ void nsMacMessagePump::DoDisk(const EventRecord& anEvent)
|
||||
//-------------------------------------------------------------------------
|
||||
extern Boolean SIOUXIsAppWindow(WindowPtr window);
|
||||
|
||||
#if USE_MENUSELECT
|
||||
void nsMacMessagePump::DoMenu(EventRecord &anEvent, long menuResult)
|
||||
{
|
||||
// The app can handle its menu commands here or
|
||||
// in the nsNativeBrowserWindow and nsNativeViewerApp
|
||||
|
||||
#if !TARGET_CARBON
|
||||
extern const PRInt16 kAppleMenuID; // Danger Will Robinson!!! - this currently requires
|
||||
extern const PRInt16 kAppleMenuID; // Danger Will Robinson!!! - this currently requires
|
||||
// APPLE_MENU_HACK to be defined in nsMenu.h
|
||||
// One of these days it'll become a non-hack
|
||||
// and things will be less convoluted
|
||||
@ -869,7 +873,6 @@ extern const PRInt16 kAppleMenuID; // Danger Will Robinson!!! - this currently r
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Note that we still give Raptor a shot at the event as it will eventually
|
||||
// handle the About... selection
|
||||
@ -877,7 +880,7 @@ extern const PRInt16 kAppleMenuID; // Danger Will Robinson!!! - this currently r
|
||||
|
||||
HiliteMenu(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
@ -934,6 +937,9 @@ PRBool nsMacMessagePump::DispatchOSEventToRaptor(
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if USE_MENUSELECT
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DispatchMenuCommandToRaptor
|
||||
@ -952,3 +958,4 @@ PRBool nsMacMessagePump::DispatchMenuCommandToRaptor(
|
||||
return handled;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -97,13 +97,17 @@ private:
|
||||
void DoMouseMove(EventRecord &anEvent);
|
||||
void DoUpdate(EventRecord &anEvent);
|
||||
void DoKey(EventRecord &anEvent);
|
||||
#if USE_MENUSELECT
|
||||
void DoMenu(EventRecord &anEvent, long menuResult);
|
||||
#endif
|
||||
void DoDisk(const EventRecord &anEvent);
|
||||
void DoActivate(EventRecord &anEvent);
|
||||
void DoIdle(EventRecord &anEvent);
|
||||
|
||||
PRBool DispatchOSEventToRaptor(EventRecord &anEvent, WindowPtr aWindow);
|
||||
#if USE_MENUSELECT
|
||||
PRBool DispatchMenuCommandToRaptor(EventRecord &anEvent, long menuResult);
|
||||
#endif
|
||||
|
||||
PRBool BrowserIsBusy();
|
||||
|
||||
|
@ -64,6 +64,7 @@ NS_EXPORT PRBool nsMacMessageSink::DispatchOSEvent(
|
||||
}
|
||||
|
||||
|
||||
#if USE_MENUSELECT
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// DispatchMenuCommand
|
||||
@ -85,6 +86,7 @@ NS_EXPORT PRBool nsMacMessageSink::DispatchMenuCommand(
|
||||
}
|
||||
return eventHandled;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
@ -75,7 +75,9 @@ private:
|
||||
public:
|
||||
|
||||
PRBool DispatchOSEvent(EventRecord &anEvent, WindowPtr aWindow);
|
||||
#if USE_MENUSELECT
|
||||
PRBool DispatchMenuCommand(EventRecord &anEvent, long menuResult, WindowPtr aWindow);
|
||||
#endif
|
||||
|
||||
static void AddRaptorWindowToList(WindowPtr wind, nsMacWindow* theRaptorWindow);
|
||||
static void RemoveRaptorWindowFromList(WindowPtr wind);
|
||||
|
@ -1322,6 +1322,8 @@ PRBool nsMacWindow::HandleOSEvent ( EventRecord& aOSEvent )
|
||||
}
|
||||
|
||||
|
||||
#if USE_MENUSELECT
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// Handle Menu commands
|
||||
@ -1337,6 +1339,8 @@ PRBool nsMacWindow::HandleMenuCommand ( EventRecord& aOSEvent, long aMenuResult
|
||||
return retVal;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Pass notification of some drag event to Gecko
|
||||
//
|
||||
|
@ -110,9 +110,11 @@ public:
|
||||
virtual PRBool HandleOSEvent(
|
||||
EventRecord& aOSEvent);
|
||||
|
||||
#if USE_MENUSELECT
|
||||
virtual PRBool HandleMenuCommand(
|
||||
EventRecord& aOSEvent,
|
||||
long aMenuResult);
|
||||
#endif
|
||||
|
||||
// be notified that a some form of drag event needs to go into Gecko
|
||||
virtual PRBool DragEvent ( unsigned int aMessage, Point aMouseGlobal, UInt16 aKeyModifiers ) ;
|
||||
|
@ -76,7 +76,8 @@ static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID);
|
||||
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
|
||||
static NS_DEFINE_CID(kMenuItemCID, NS_MENUITEM_CID);
|
||||
|
||||
NS_IMPL_ISUPPORTS5(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver, nsIChangeManager, nsISupportsWeakReference)
|
||||
NS_IMPL_ISUPPORTS6(nsMenuBarX, nsIMenuBar, nsIMenuListener, nsIDocumentObserver,
|
||||
nsIChangeManager, nsIMenuCommandDispatcher, nsISupportsWeakReference)
|
||||
|
||||
MenuRef nsMenuBarX::sAppleMenu = nsnull;
|
||||
EventHandlerUPP nsMenuBarX::sCommandEventHandler = nsnull;
|
||||
@ -86,12 +87,9 @@ EventHandlerUPP nsMenuBarX::sCommandEventHandler = nsnull;
|
||||
// nsMenuBarX constructor
|
||||
//
|
||||
nsMenuBarX::nsMenuBarX()
|
||||
: mNumMenus(0), mParent(nsnull), mIsMenuBarAdded(PR_FALSE), mDocument(nsnull), mCurrentCommandID(1)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mNumMenus = 0;
|
||||
mParent = nsnull;
|
||||
mIsMenuBarAdded = PR_FALSE;
|
||||
mDocument = nsnull;
|
||||
|
||||
OSStatus status = ::CreateNewMenu(0, 0, &mRootMenu);
|
||||
NS_ASSERTION(status == noErr, "nsMenuBarX::nsMenuBarX: creation of root menu failed.");
|
||||
@ -246,8 +244,6 @@ nsMenuBarX :: RegisterAsDocumentObserver ( nsIWebShell* inWebShell )
|
||||
} // RegisterAsDocumentObesrver
|
||||
|
||||
|
||||
#if TARGET_CARBON
|
||||
|
||||
//
|
||||
// AquifyMenuBar
|
||||
//
|
||||
@ -271,20 +267,34 @@ nsMenuBarX :: AquifyMenuBar ( )
|
||||
HideItem ( domDoc, NS_LITERAL_STRING("menu_PrefsSeparator"), nsnull );
|
||||
HideItem ( domDoc, NS_LITERAL_STRING("menu_preferences"), getter_AddRefs(mPrefItemContent) );
|
||||
}
|
||||
|
||||
} // AquifyMenuBar
|
||||
|
||||
|
||||
//
|
||||
// InstallCommandEventHandler
|
||||
//
|
||||
// Grab our window and install an event handler to handle command events which are
|
||||
// used to drive the action when the user chooses an item from a menu. We have to install
|
||||
// it on the window because the menubar isn't in the event chain for a menu command event.
|
||||
//
|
||||
OSStatus
|
||||
nsMenuBarX :: InstallCommandEventHandler ( )
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
|
||||
// Install the command handler to deal with prefs/quit. We have to install it on the window because the
|
||||
// menubar isn't in the event chain for a menu command event. Don't enable the prefs item
|
||||
// just yet, wait until we actually find a pref node in the DOM.
|
||||
WindowRef myWindow = NS_REINTERPRET_CAST(WindowRef, mParent->GetNativeData(NS_NATIVE_DISPLAY));
|
||||
NS_ASSERTION ( myWindow, "Can't get WindowRef to install command handler!" );
|
||||
if ( myWindow && sCommandEventHandler ) {
|
||||
EventTypeSpec commandEventList[] = { {kEventClassCommand, kEventCommandProcess},
|
||||
{kEventClassCommand, kEventCommandUpdateStatus} };
|
||||
OSStatus err = ::InstallWindowEventHandler ( myWindow, sCommandEventHandler, 2, commandEventList, this, NULL );
|
||||
const EventTypeSpec commandEventList[] = { {kEventClassCommand, kEventCommandProcess},
|
||||
{kEventClassCommand, kEventCommandUpdateStatus} };
|
||||
err = ::InstallWindowEventHandler ( myWindow, sCommandEventHandler, 2, commandEventList, this, NULL );
|
||||
NS_ASSERTION ( err == noErr, "Uh oh, command handler not installed" );
|
||||
}
|
||||
|
||||
} // AquifyMenuBar
|
||||
|
||||
return err;
|
||||
|
||||
} // InstallCommandEventHandler
|
||||
|
||||
|
||||
//
|
||||
@ -292,9 +302,6 @@ nsMenuBarX :: AquifyMenuBar ( )
|
||||
//
|
||||
// Processes Command carbon events from enabling/selecting of items in the menu.
|
||||
//
|
||||
// NOTE: eventually, all menu dispatching will go through this routine, for now, we only
|
||||
// dispatch prefs and quit this way
|
||||
//
|
||||
pascal OSStatus
|
||||
nsMenuBarX :: CommandEventHandler ( EventHandlerCallRef inHandlerChain, EventRef inEvent, void* userData )
|
||||
{
|
||||
@ -327,12 +334,36 @@ nsMenuBarX :: CommandEventHandler ( EventHandlerCallRef inHandlerChain, EventRef
|
||||
handled = noErr;
|
||||
break;
|
||||
}
|
||||
|
||||
#if NOT_YET
|
||||
|
||||
case kHICommandAbout:
|
||||
{
|
||||
// the 'about' command is special because we don't have a nsIMenu or nsIMenuItem
|
||||
// for the apple menu. Grovel for the content node with an id of "aboutName"
|
||||
// and call it directly.
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc = do_QueryInterface(self->mDocument);
|
||||
if ( xulDoc ) {
|
||||
nsCOMPtr<nsIDOMElement> domElement;
|
||||
xulDoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(domElement));
|
||||
nsCOMPtr<nsIContent> aboutContent ( do_QueryInterface(domElement) );
|
||||
self->ExecuteCommand(aboutContent);
|
||||
}
|
||||
handled = noErr;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// given the commandID, look it up in our hashtable and dispatch to
|
||||
// that content node. Recall that we store weak pointers to the content
|
||||
// nodes in the hash table.
|
||||
nsPRUint32Key key ( command.commandID );
|
||||
nsIMenuItem* content = NS_REINTERPRET_CAST(nsIMenuItem*, self->mObserverTable.Get(&key));
|
||||
if ( content )
|
||||
content->DoCommand();
|
||||
handled = noErr;
|
||||
break;
|
||||
}
|
||||
|
||||
} // switch on commandID
|
||||
break;
|
||||
}
|
||||
@ -410,9 +441,6 @@ nsMenuBarX :: HideItem ( nsIDOMDocument* inDoc, nsAReadableString & inID, nsICon
|
||||
} // HideItem
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
nsEventStatus
|
||||
nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow,
|
||||
void * menubarNode, void * aWebShell )
|
||||
@ -426,14 +454,15 @@ nsMenuBarX::MenuConstruct( const nsMenuEvent & aMenuEvent, nsIWidget* aParentWin
|
||||
|
||||
Create(aParentWindow);
|
||||
|
||||
#if TARGET_CARBON
|
||||
// if we're on X (using aqua UI guidelines for menus), remove quit and prefs
|
||||
// from our menubar.
|
||||
SInt32 result = 0L;
|
||||
OSStatus err = ::Gestalt ( gestaltMenuMgrAttr, &result );
|
||||
if ( !err && (result & gestaltMenuMgrAquaLayoutMask) )
|
||||
AquifyMenuBar();
|
||||
#endif
|
||||
err = InstallCommandEventHandler();
|
||||
if ( err )
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
|
||||
if (webShell) RegisterAsDocumentObserver(webShell);
|
||||
@ -613,6 +642,8 @@ nsMenuBarX :: CreateAppleMenu ( nsIMenu* inMenu )
|
||||
::CFRelease(labelRef);
|
||||
}
|
||||
|
||||
::SetMenuItemCommandID(sAppleMenu, 1, kHICommandAbout);
|
||||
|
||||
::AppendMenu(sAppleMenu, "\p-");
|
||||
}
|
||||
|
||||
@ -937,6 +968,56 @@ nsMenuBarX :: Lookup ( nsIContent *aContent, nsIChangeObserver **_retval )
|
||||
#pragma mark -
|
||||
|
||||
|
||||
//
|
||||
// Implementation methods for nsIMenuCommandDispatcher
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Register
|
||||
//
|
||||
// Given a menu item, creates a unique 4-character command ID and
|
||||
// maps it to the item. Returns the id for use by the client.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarX :: Register ( nsIMenuItem* inMenuItem, PRUint32* outCommandID )
|
||||
{
|
||||
// no real need to check for uniqueness. We always start afresh with each
|
||||
// window at 1. Even if we did get close to the reserved Apple command id's,
|
||||
// those don't start until at least ' ', which is integer 538976288. If
|
||||
// we have that many menu items in one window, I think we have other problems.
|
||||
|
||||
// put it in the table, set out param for client
|
||||
nsPRUint32Key key ( mCurrentCommandID );
|
||||
mObserverTable.Put ( &key, inMenuItem );
|
||||
*outCommandID = mCurrentCommandID;
|
||||
|
||||
// make id unique for next time
|
||||
++mCurrentCommandID;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Unregister
|
||||
//
|
||||
// Removes the mapping between the given 4-character command ID
|
||||
// and its associated menu item.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
nsMenuBarX :: Unregister ( PRUint32 inCommandID )
|
||||
{
|
||||
nsPRUint32Key key ( inCommandID );
|
||||
mObserverTable.Remove ( &key );
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
//
|
||||
// WebShellToPresContext
|
||||
//
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIChangeManager.h"
|
||||
#include "nsIMenuCommandDispatcher.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
@ -76,6 +77,7 @@ class nsMenuBarX : public nsIMenuBar,
|
||||
public nsIMenuListener,
|
||||
public nsIDocumentObserver,
|
||||
public nsIChangeManager,
|
||||
public nsIMenuCommandDispatcher,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
@ -86,6 +88,7 @@ public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICHANGEMANAGER
|
||||
NS_DECL_NSIMENUCOMMANDDISPATCHER
|
||||
|
||||
// nsIMenuListener interface
|
||||
nsEventStatus MenuItemSelected(const nsMenuEvent & aMenuEvent);
|
||||
@ -171,30 +174,29 @@ protected:
|
||||
void GetDocument ( nsIWebShell* inWebShell, nsIDocument** outDocument ) ;
|
||||
void RegisterAsDocumentObserver ( nsIWebShell* inWebShell ) ;
|
||||
|
||||
#if TARGET_CARBON
|
||||
// Make our menubar conform to Aqua UI guidelines
|
||||
void AquifyMenuBar ( ) ;
|
||||
void HideItem ( nsIDOMDocument* inDoc, nsAReadableString & inID, nsIContent** outHiddenNode ) ;
|
||||
OSStatus InstallCommandEventHandler ( ) ;
|
||||
|
||||
// command handler for some special menu items (prefs/quit/etc)
|
||||
pascal static OSStatus CommandEventHandler ( EventHandlerCallRef inHandlerChain,
|
||||
EventRef inEvent, void* userData ) ;
|
||||
nsEventStatus ExecuteCommand ( nsIContent* inDispatchTo ) ;
|
||||
#endif
|
||||
|
||||
// build the Apple menu shared by all menu bars.
|
||||
nsresult CreateAppleMenu ( nsIMenu* inMenu ) ;
|
||||
|
||||
nsHashtable mObserverTable; // stores observers for content change notification
|
||||
nsHashtable mCommandMapTable; // maps CommandIDs to content nodes for CarbonEvent item selection
|
||||
PRUint32 mCurrentCommandID; // unique command id (per menu-bar) to give to next item that asks
|
||||
|
||||
PRUint32 mNumMenus;
|
||||
nsSupportsArray mMenusArray; // holds refs
|
||||
nsCOMPtr<nsIContent> mMenuBarContent; // menubar content node, strong ref
|
||||
#if TARGET_CARBON
|
||||
nsCOMPtr<nsIContent> mPrefItemContent; // on X, holds the content node for the prefs item that has
|
||||
// been removed from the menubar
|
||||
nsCOMPtr<nsIContent> mQuitItemContent; // as above, but for quit
|
||||
#endif
|
||||
nsIWidget* mParent; // weak ref
|
||||
|
||||
PRBool mIsMenuBarAdded;
|
||||
@ -206,9 +208,7 @@ protected:
|
||||
|
||||
static MenuRef sAppleMenu; // AppleMenu shared by all menubars
|
||||
|
||||
#if TARGET_CARBON
|
||||
static EventHandlerUPP sCommandEventHandler; // carbon event handler for commands, shared
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // nsMenuBarX_h__
|
||||
|
@ -201,38 +201,14 @@ NS_METHOD nsMenuItemX::IsSeparator(PRBool & aIsSep)
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItemX::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
switch ( mMenuType ) {
|
||||
case eCheckbox:
|
||||
SetChecked(!mIsChecked);
|
||||
break;
|
||||
|
||||
case eRadio:
|
||||
{
|
||||
// we only want to muck with things if we were selected and we're not
|
||||
// already checked.
|
||||
if ( mIsChecked )
|
||||
break;
|
||||
SetChecked(PR_TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
case eRegular:
|
||||
break; // do nothing special
|
||||
|
||||
} // which menu type
|
||||
|
||||
DoCommand();
|
||||
// this is all handled by Carbon Events
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuItemX::MenuSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
//if(mXULCommandListener)
|
||||
// return mXULCommandListener->MenuSelected(aMenuEvent);
|
||||
|
||||
DoCommand();
|
||||
return nsEventStatus_eIgnore;
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -309,7 +285,7 @@ NS_METHOD nsMenuItemX::DoCommand()
|
||||
}
|
||||
else
|
||||
mContent->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
|
||||
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include "nsIMenuItem.h"
|
||||
#include "nsIMenuListener.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIMenuCommandDispatcher.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsReadableUtils.h"
|
||||
@ -293,6 +294,15 @@ NS_METHOD nsMenuX::AddMenuItem(nsIMenuItem * aMenuItem)
|
||||
|
||||
::SetMenuItemModifiers(mMacMenuHandle, currItemIndex, macModifiers);
|
||||
|
||||
// set its command. we get the unique command id from the menubar
|
||||
nsCOMPtr<nsIMenuCommandDispatcher> dispatcher ( do_QueryInterface(mManager) );
|
||||
if ( dispatcher ) {
|
||||
PRUint32 commandID = 0L;
|
||||
dispatcher->Register(aMenuItem, &commandID);
|
||||
if ( commandID )
|
||||
::SetMenuItemCommandID(mMacMenuHandle, currItemIndex, commandID);
|
||||
}
|
||||
|
||||
PRBool isEnabled;
|
||||
aMenuItem->GetEnabled(&isEnabled);
|
||||
if(isEnabled)
|
||||
@ -412,8 +422,20 @@ NS_METHOD nsMenuX::RemoveItem(const PRUint32 aPos)
|
||||
//-------------------------------------------------------------------------
|
||||
NS_METHOD nsMenuX::RemoveAll()
|
||||
{
|
||||
if (mMacMenuHandle != NULL)
|
||||
if (mMacMenuHandle != NULL) {
|
||||
// clear command id's
|
||||
nsCOMPtr<nsIMenuCommandDispatcher> dispatcher ( do_QueryInterface(mManager) );
|
||||
if ( dispatcher ) {
|
||||
for ( int i = 1; i <= mNumMenuItems; ++i ) {
|
||||
PRUint32 commandID = 0L;
|
||||
OSErr err = ::GetMenuItemCommandID(mMacMenuHandle, i, (unsigned long*)&commandID);
|
||||
if ( !err )
|
||||
dispatcher->Unregister(commandID);
|
||||
}
|
||||
}
|
||||
::DeleteMenuItems(mMacMenuHandle, 1, ::CountMenuItems(mMacMenuHandle));
|
||||
}
|
||||
|
||||
mMenuItemsArray.Clear(); // remove all items
|
||||
return NS_OK;
|
||||
}
|
||||
@ -455,110 +477,8 @@ NS_METHOD nsMenuX::RemoveMenuListener(nsIMenuListener * aMenuListener)
|
||||
//-------------------------------------------------------------------------
|
||||
nsEventStatus nsMenuX::MenuItemSelected(const nsMenuEvent & aMenuEvent)
|
||||
{
|
||||
//printf("MenuItemSelected called \n");
|
||||
nsEventStatus eventStatus = nsEventStatus_eIgnore;
|
||||
|
||||
// Determine if this is the correct menu to handle the event. We can't use
|
||||
// the HiWord of the command because of MenuSelect bugs in Carbon. Use
|
||||
// the menuID we've been tracking manually instead. However, we don't get
|
||||
// the carbon events for the apple menu, so if MenuSelect() tells us we've hit
|
||||
// the apple menu (where there are no submenus we care about), it is
|
||||
// actually correct and |gCurrentlyTrackedMenuID| is wrong. Go figure.
|
||||
MenuID probablyWrongMenuID = HiWord(((nsMenuEvent)aMenuEvent).mCommand);
|
||||
if ( probablyWrongMenuID == nsMenuBarX::kAppleMenuID )
|
||||
gCurrentlyTrackedMenuID = nsMenuBarX::kAppleMenuID;
|
||||
MenuID menuID = gCurrentlyTrackedMenuID;
|
||||
|
||||
if( menuID == nsMenuBarX::kAppleMenuID ) {
|
||||
PRInt16 menuItemID = LoWord(((nsMenuEvent)aMenuEvent).mCommand);
|
||||
if (menuItemID == 1) {
|
||||
/* handle about app here */
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
// Go find the about menu item
|
||||
if (!mMenuContent)
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
mMenuContent->GetDocument(*getter_AddRefs(doc));
|
||||
if (!doc)
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
nsCOMPtr<nsIDOMXULDocument> xulDoc = do_QueryInterface(doc);
|
||||
if (!xulDoc) {
|
||||
NS_ERROR("nsIDOMDocument to nsIDOMXULDocument QI failed.");
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
// "aboutName" is the element id for the "About &shortBrandName;"
|
||||
// <menuitem/>. This is the glue code which causes any script code
|
||||
// in the <menuitem/> to be executed.
|
||||
nsCOMPtr<nsIDOMElement> domElement;
|
||||
xulDoc->GetElementById(NS_LITERAL_STRING("aboutName"), getter_AddRefs(domElement));
|
||||
if (!domElement)
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
|
||||
// Now get the pres context so we can execute the command
|
||||
nsCOMPtr<nsIWebShell> webShell = do_QueryReferent(mWebShellWeakRef);
|
||||
if (!webShell)
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
nsCOMPtr<nsIPresContext> presContext;
|
||||
MenuHelpersX::WebShellToPresContext(webShell, getter_AddRefs(presContext));
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsMouseEvent event;
|
||||
event.eventStructType = NS_MOUSE_EVENT;
|
||||
event.message = NS_XUL_COMMAND;
|
||||
|
||||
nsCOMPtr<nsIContent> contentNode = do_QueryInterface(domElement);
|
||||
if (!contentNode)
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
|
||||
rv = contentNode->HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
else if (mMacMenuID == menuID)
|
||||
{
|
||||
// Call MenuItemSelected on the correct nsMenuItem
|
||||
PRInt16 menuItemID = LoWord(((nsMenuEvent)aMenuEvent).mCommand);
|
||||
|
||||
nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenuItemsArray.ElementAt(menuItemID - 1));
|
||||
NS_ASSERTION(menuSupports, "Somehow our item list was torn down prematurely");
|
||||
nsCOMPtr<nsIMenuListener> menuListener = do_QueryInterface(menuSupports);
|
||||
if (menuListener)
|
||||
{
|
||||
// call our ondestroy handler now because the menu is going away.
|
||||
// do it now before sending the event into the dom in case our window
|
||||
// goes away.
|
||||
OnDestroy();
|
||||
|
||||
eventStatus = menuListener->MenuItemSelected(aMenuEvent);
|
||||
if(nsEventStatus_eIgnore != eventStatus)
|
||||
return eventStatus;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure none of our submenus are the ones that should be handling this
|
||||
PRUint32 numItems;
|
||||
mMenuItemsArray.Count(&numItems);
|
||||
for (PRUint32 i = numItems; i > 0; i--)
|
||||
{
|
||||
nsCOMPtr<nsISupports> menuSupports = getter_AddRefs(mMenuItemsArray.ElementAt(i - 1));
|
||||
nsCOMPtr<nsIMenu> submenu = do_QueryInterface(menuSupports);
|
||||
nsCOMPtr<nsIMenuListener> menuListener = do_QueryInterface(submenu);
|
||||
if (menuListener)
|
||||
{
|
||||
// call our ondestroy handler now because the menu is going away.
|
||||
// do it now before sending the event into the dom in case our window
|
||||
// goes away.
|
||||
OnDestroy();
|
||||
|
||||
eventStatus = menuListener->MenuItemSelected(aMenuEvent);
|
||||
if(nsEventStatus_eIgnore != eventStatus)
|
||||
return eventStatus;
|
||||
}
|
||||
}
|
||||
|
||||
return eventStatus;
|
||||
// all this is now handled by Carbon Events.
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -143,9 +143,7 @@ protected:
|
||||
nsSupportsArray mMenuItemsArray; // array holds refs
|
||||
|
||||
nsISupports* mParent; // weak, my parent owns me
|
||||
// nsIMenu* mMenuParent;
|
||||
// nsIMenuBar* mMenuBarParent;
|
||||
nsIChangeManager* mManager; // weak ref, it will outlive us
|
||||
nsIChangeManager* mManager; // weak ref, it will outlive us [menubar]
|
||||
nsWeakPtr mWebShellWeakRef; // weak ref to webshell
|
||||
nsCOMPtr<nsIContent> mMenuContent; // the |menu| tag, strong ref
|
||||
nsCOMPtr<nsIMenuListener> mListener; // strong ref
|
||||
|
Loading…
Reference in New Issue
Block a user