Re-landing. Decomtaminate native menu system. Add new native menu API. Lots of cleanup for the native menu system code. Memory usage and speed improvements. b=433952 r=bent r=kreeger sr=roc

This commit is contained in:
Josh Aas 2008-06-28 03:55:30 -04:00
Родитель 5e7f902e4c
Коммит b499ac5fe0
39 изменённых файлов: 1365 добавлений и 1901 удалений

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

@ -47,7 +47,7 @@
interface nsIDOMElement;
[scriptable, uuid(993da427-2ac3-4766-8485-21a236d258e4)]
[scriptable, uuid(ef136142-9925-45f4-a3e4-6f0d275c6aa8)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -160,6 +160,15 @@ interface nsIDOMWindowUtils : nsISupports {
in AString aCharacters,
in AString aUnmodifiedCharacters);
/**
* See nsIWidget::ActivateNativeMenuItemAt
*
* Cannot be accessed from unprivileged context (not content-accessible)
* Will throw a DOM security error if called without UniversalXPConnect
* privileges.
*/
void activateNativeMenuItemAt(in AString indexString);
/**
* Focus the element aElement. The element should be in the same document
* that the window is displaying. Pass null to blur the element, if any,

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

@ -308,6 +308,22 @@ nsDOMWindowUtils::SendNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
aModifiers, aCharacters, aUnmodifiedCharacters);
}
NS_IMETHODIMP
nsDOMWindowUtils::ActivateNativeMenuItemAt(const nsAString& indexString)
{
PRBool hasCap = PR_FALSE;
if (NS_FAILED(nsContentUtils::GetSecurityManager()->IsCapabilityEnabled("UniversalXPConnect", &hasCap))
|| !hasCap)
return NS_ERROR_DOM_SECURITY_ERR;
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
return NS_ERROR_FAILURE;
return widget->ActivateNativeMenuItemAt(indexString);
}
nsIWidget*
nsDOMWindowUtils::GetWidget()
{

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

@ -64,7 +64,7 @@ EXPORTS = \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
EXPORTS += nsIMenuBar.h
EXPORTS += nsINativeMenuService.h
endif
ifeq ($(MOZ_WIDGET_TOOLKIT),os2)

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

@ -1,141 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIMenuBar_h__
#define nsIMenuBar_h__
#include "nsISupports.h"
#include "nsString.h"
#include "nsIMenu.h"
class nsIWidget;
// F81C6D64-B260-44ED-9289-2E410A130E35
#define NS_IMENUBAR_IID \
{ 0xF81C6D64, 0xB260, 0x44ED, \
{ 0x92, 0x89, 0x2E, 0x41, 0x0A, 0x13, 0x0E, 0x35 } }
/**
* MenuBar widget
*/
class nsIMenuBar : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMENUBAR_IID)
/**
* Creates the MenuBar
*
*/
NS_IMETHOD Create(nsIWidget * aParent) = 0;
/**
* Get the MenuBar's Parent. This addrefs.
*
*/
NS_IMETHOD GetParent(nsIWidget *&aParent) = 0;
/**
* Set the MenuBar's Parent
*
*/
NS_IMETHOD SetParent(nsIWidget *aParent) = 0;
/**
* Adds the Menu
*
*/
NS_IMETHOD AddMenu(nsIMenu * aMenu) = 0;
/**
* Returns the number of menus
*
*/
NS_IMETHOD GetMenuCount(PRUint32 &aCount) = 0;
/**
* Returns a Menu Item at a specified Index
*
*/
NS_IMETHOD GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu) = 0;
/**
* Inserts a Menu at a specified Index
*
*/
NS_IMETHOD InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu) = 0;
/**
* Removes an Menu from a specified Index
*
*/
NS_IMETHOD RemoveMenu(const PRUint32 aCount) = 0;
/**
* Removes all the Menus
*
*/
NS_IMETHOD RemoveAll() = 0;
/**
* Gets Native MenuHandle
*
*/
NS_IMETHOD GetNativeData(void*& aData) = 0;
/**
* Sets Native MenuHandle. Temporary hack for mac until
* nsMenuBar does it's own construction
*/
NS_IMETHOD SetNativeData(void* aData) = 0;
/**
* Draw the menubar
*
*/
NS_IMETHOD Paint() = 0;
/**
* Construct the menubar
*
*/
NS_IMETHOD MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, void * aMenuNode) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIMenuBar, NS_IMENUBAR_IID)
#endif

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

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsINativeMenuService_h_
#define nsINativeMenuService_h_
#include "nsISupports.h"
class nsIWidget;
class nsIContent;
// {90DF88F9-F084-4EF3-829A-49496E636DED}
#define NS_INATIVEMENUSERVICE_IID \
{ 0x90DF88F9, 0xF084, 0x4EF3, \
{ 0x82, 0x9A, 0x49, 0x49, 0x6E, 0x63, 0x6D, 0xED} }
class nsINativeMenuService : public nsISupports {
public:
// Given a top-level window widget and a menu bar DOM node, sets up native
// menus. Once created, native menus are controlled via the DOM, including
// destruction.
NS_IMETHOD CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode)=0;
};
#endif // nsINativeMenuService_h_

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

@ -55,7 +55,6 @@ class nsIDeviceContext;
class nsIRegion;
struct nsRect;
struct nsFont;
class nsIMenuBar;
class nsIEventListener;
class nsIRollupListener;
class nsGUIEvent;
@ -95,10 +94,10 @@ typedef nsEventStatus (*PR_CALLBACK EVENT_CALLBACK)(nsGUIEvent *event);
#define NS_NATIVE_PLUGIN_PORT_CG 101
#endif
// 517a0eef-cd1c-48b3-96f0-e341a50f120d
// 00e25b3d-c872-4985-a15e-8e650b7b8ff6
#define NS_IWIDGET_IID \
{ 0x517a0eef, 0xcd1c, 0x48b3, \
{ 0x96, 0xf0, 0xe3, 0x41, 0xa5, 0x0f, 0x12, 0x0d } }
{ 0x00e25b3d, 0xc872, 0x4985, \
{ 0xa1, 0x5e, 0x8e, 0x65, 0x0b, 0x7b, 0x8f, 0xf6 } }
// Hide the native window systems real window type so as to avoid
// including native window system types and APIs. This is necessary
@ -879,7 +878,7 @@ class nsIWidget : public nsISupports {
* @param aMenuBar the menubar
*/
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar) = 0;
NS_IMETHOD SetMenuBar(void* aMenuBar) = 0;
/**
* Set the widget's MenuBar's visibility
@ -1105,6 +1104,20 @@ class nsIWidget : public nsISupports {
const nsAString& aCharacters,
const nsAString& aUnmodifiedCharacters) = 0;
/**
* Activates a native menu item at the position specified by the index
* string. The index string is a string of positive integers separated
* by the "|" (pipe) character. The last integer in the string represents
* the item index in a submenu located using the integers prior to it.
*
* Example: 1|0|4
* In this string, the first integer represents the top-level submenu
* in the native menu bar. Since the integer is 1, it is the second submeu
* in the native menu bar. Within that, the first item (index 0) is a
* submenu, and we want to activate the 5th item within that submenu.
*/
virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) = 0;
protected:
// keep the list of children. We also keep track of our siblings.
// The ownership model is as follows: parent holds a strong ref to

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

@ -79,20 +79,10 @@
// Menus
//-----------------------------------------------------------
// {BC658C81-4BEB-11d2-8DBB-00609703C14E}
#define NS_MENUBAR_CID \
{ 0xbc658c81, 0x4beb, 0x11d2, \
{ 0x8d, 0xbb, 0x0, 0x60, 0x97, 0x3, 0xc1, 0x4e } }
// {35A3DEC1-4992-11d2-8DBA-00609703C14E}
#define NS_MENU_CID \
{ 0x35a3dec1, 0x4992, 0x11d2, \
{ 0x8d, 0xba, 0x0, 0x60, 0x97, 0x3, 0xc1, 0x4e } }
// {7F045771-4BEB-11d2-8DBB-00609703C14E}
#define NS_MENUITEM_CID \
{ 0x7f045771, 0x4beb, 0x11d2, \
{ 0x8d, 0xbb, 0x0, 0x60, 0x97, 0x3, 0xc1, 0x4e } }
// {0B3FE5AA-BC72-4303-85AE-76365DF1251D}
#define NS_NATIVEMENUSERVICE_CID \
{ 0x0B3FE5AA, 0xBC72, 0x4303, \
{ 0x85, 0xAE, 0x76, 0x36, 0x5D, 0xF1, 0x25, 0x1D} }
// {F6CD4F21-53AF-11d2-8DC4-00609703C14E}
#define NS_POPUPMENU_CID \

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

@ -48,8 +48,6 @@
#include "nsIWidget.h"
#include "nsIMenuBar.h"
#include "nsIMouseListener.h"
#include "nsIEventListener.h"
#include "nsString.h"
@ -164,7 +162,7 @@ public:
NS_IMETHOD SetColorMap(nsColorMap *aColorMap);
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsRect *aClipRect);
NS_IMETHOD SetTitle(const nsAString& aTitle);
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_ERROR_FAILURE; }
NS_IMETHOD WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect);
NS_IMETHOD ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect);

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

@ -66,7 +66,7 @@ REQUIRES = xpcom \
intl \
exthandler \
appshell \
lcms \
lcms \
thebes \
js \
xpconnect \
@ -84,8 +84,6 @@ endif
EXPORTS = \
mozView.h \
nsChangeObserver.h \
nsIMenu.h \
nsIMenuItem.h \
$(NULL)
CMMSRCS = \
@ -95,6 +93,7 @@ CMMSRCS = \
nsMenuBarX.mm \
nsMenuItemX.mm \
nsMenuItemIconX.mm \
nsMenuUtilsX.mm \
nsFilePicker.mm \
nsDragService.mm \
nsToolkit.mm \

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

@ -61,7 +61,6 @@
#include "nsIEventListener.h"
#include "nsString.h"
#include "nsIDragService.h"
#include "nsIMenuBar.h"
#include "nsplugindefs.h"
@ -291,7 +290,7 @@ public:
void LocalToWindowCoordinate(nscoord& aX, nscoord& aY) { ConvertToDeviceCoordinates(aX, aY); }
void LocalToWindowCoordinate(nsRect& aRect) { ConvertToDeviceCoordinates(aRect.x, aRect.y); }
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar);
NS_IMETHOD SetMenuBar(void* aMenuBar);
NS_IMETHOD ShowMenuBar(PRBool aShow);
NS_IMETHOD GetPreferredSize(PRInt32& aWidth, PRInt32& aHeight);
@ -305,6 +304,8 @@ public:
NS_IMETHOD GetAttention(PRInt32 aCycleCount);
NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString);
// nsIPluginWidget
NS_IMETHOD GetPluginClipRect(nsRect& outClipRect, nsPoint& outOrigin, PRBool& outWidgetVisible);
NS_IMETHOD StartDrawPlugin();

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

@ -971,7 +971,7 @@ NS_IMETHODIMP nsChildView::SetColorMap(nsColorMap *aColorMap)
}
NS_IMETHODIMP nsChildView::SetMenuBar(nsIMenuBar * aMenuBar)
NS_IMETHODIMP nsChildView::SetMenuBar(void* aMenuBar)
{
return NS_ERROR_FAILURE; // subviews don't have menu bars
}
@ -1373,6 +1373,51 @@ nsresult nsChildView::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// Used for testing native menu system structure and event handling.
NS_IMETHODIMP nsChildView::ActivateNativeMenuItemAt(const nsAString& indexString)
{
NSString* title = [NSString stringWithCharacters:indexString.BeginReading() length:indexString.Length()];
NSArray* indexes = [title componentsSeparatedByString:@"|"];
unsigned int indexCount = [indexes count];
if (indexCount == 0)
return NS_OK;
NSMenu* currentSubmenu = [NSApp mainMenu];
for (unsigned int i = 0; i < (indexCount - 1); i++) {
NSMenu* newSubmenu = nil;
int targetIndex;
// We remove the application menu from consideration for the top-level menu
if (i == 0)
targetIndex = [[indexes objectAtIndex:i] intValue] + 1;
else
targetIndex = [[indexes objectAtIndex:i] intValue];
int itemCount = [currentSubmenu numberOfItems];
if (targetIndex < itemCount) {
NSMenuItem* menuItem = [currentSubmenu itemAtIndex:targetIndex];
if ([menuItem hasSubmenu])
newSubmenu = [menuItem submenu];
}
if (newSubmenu)
currentSubmenu = newSubmenu;
else
return NS_ERROR_FAILURE;
}
int itemCount = [currentSubmenu numberOfItems];
int targetIndex = [[indexes objectAtIndex:(indexCount - 1)] intValue];
if (targetIndex < itemCount) {
// NSLog(@"Performing action for native menu item titled: %@\n",
// [[currentSubmenu itemAtIndex:targetIndex] title]);
[currentSubmenu performActionForItemAtIndex:targetIndex];
}
else {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
#pragma mark -

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

@ -47,6 +47,7 @@
#include "nsIXULWindow.h"
#include "nsIBaseWindow.h"
#include "nsIServiceManager.h"
#include "nsMenuUtilsX.h"
float nsCocoaUtils::MenuBarScreenHeight()
{
@ -191,7 +192,7 @@ void nsCocoaUtils::PrepareForNativeAppModalDialog()
// Don't do anything if this is embedding. We'll assume that if there is no hidden
// window we shouldn't do anything, and that should cover the embedding case.
nsIMenuBar* hiddenWindowMenuBar = MenuHelpersX::GetHiddenWindowMenuBar();
nsMenuBarX* hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar();
if (!hiddenWindowMenuBar)
return;
@ -212,7 +213,7 @@ void nsCocoaUtils::PrepareForNativeAppModalDialog()
[firstMenuItem release];
// Add standard edit menu
[newMenuBar addItem:MenuHelpersX::GetStandardEditMenuItem()];
[newMenuBar addItem:nsMenuUtilsX::GetStandardEditMenuItem()];
// Show the new menu bar
[NSApp setMainMenu:newMenuBar];
@ -228,7 +229,7 @@ void nsCocoaUtils::CleanUpAfterNativeAppModalDialog()
// Don't do anything if this is embedding. We'll assume that if there is no hidden
// window we shouldn't do anything, and that should cover the embedding case.
nsIMenuBar* hiddenWindowMenuBar = MenuHelpersX::GetHiddenWindowMenuBar();
nsMenuBarX* hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar();
if (!hiddenWindowMenuBar)
return;

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

@ -46,9 +46,11 @@
#include "nsBaseWidget.h"
#include "nsPIWidgetCocoa.h"
#include "nsAutoPtr.h"
class nsCocoaWindow;
class nsChildView;
class nsMenuBarX;
typedef struct _nsCocoaWindowList {
_nsCocoaWindowList() : prev(NULL), window(NULL) {}
@ -210,8 +212,8 @@ public:
NS_IMETHOD SetModal(PRBool aState);
NS_IMETHOD IsVisible(PRBool & aState);
NS_IMETHOD SetFocus(PRBool aState=PR_FALSE);
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar);
virtual nsIMenuBar* GetMenuBar();
NS_IMETHOD SetMenuBar(void* aMenuBar);
virtual nsMenuBarX* GetMenuBar();
NS_IMETHOD ShowMenuBar(PRBool aShow);
NS_IMETHOD WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect);
NS_IMETHOD ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect);
@ -275,7 +277,7 @@ protected:
nsIWidget* mParent; // if we're a popup, this is our parent [WEAK]
NSWindow* mWindow; // our cocoa window [STRONG]
WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG]
nsCOMPtr<nsIMenuBar> mMenuBar;
nsRefPtr<nsMenuBarX> mMenuBar;
NSWindow* mSheetWindowParent; // if this is a sheet, this is the NSWindow it's attached to
nsChildView* mPopupContentView; // if this is a popup, this is its content widget

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

@ -64,6 +64,7 @@
#include "nsPIDOMWindow.h"
#include "nsIDOMElement.h"
#include "nsMenuBarX.h"
#include "nsMenuUtilsX.h"
#include "gfxPlatform.h"
#include "lcms.h"
@ -1117,13 +1118,6 @@ NS_IMETHODIMP nsCocoaWindow::GetChildSheet(PRBool aShown, nsCocoaWindow** _retva
}
NS_IMETHODIMP nsCocoaWindow::GetMenuBar(nsIMenuBar** menuBar)
{
*menuBar = mMenuBar;
return NS_OK;
}
NS_IMETHODIMP nsCocoaWindow::GetRealParent(nsIWidget** parent)
{
*parent = mParent;
@ -1200,15 +1194,15 @@ nsCocoaWindow::ReportSizeEvent(NSRect *r)
}
NS_IMETHODIMP nsCocoaWindow::SetMenuBar(nsIMenuBar *aMenuBar)
NS_IMETHODIMP nsCocoaWindow::SetMenuBar(void *aMenuBar)
{
if (mMenuBar)
mMenuBar->SetParent(nsnull);
mMenuBar = aMenuBar;
mMenuBar = static_cast<nsMenuBarX*>(aMenuBar);
// We paint the hidden window menu bar if no other menu bar has been painted
// yet so that some reasonable menu bar is displayed when the app starts up.
if (!gSomeMenuBarPainted && mMenuBar && (MenuHelpersX::GetHiddenWindowMenuBar() == mMenuBar))
if (!gSomeMenuBarPainted && mMenuBar && (nsMenuUtilsX::GetHiddenWindowMenuBar() == mMenuBar))
mMenuBar->Paint();
return NS_OK;
@ -1264,7 +1258,7 @@ NS_IMETHODIMP nsCocoaWindow::ScreenToWidget(const nsRect& aOldRect, nsRect& aNew
}
nsIMenuBar* nsCocoaWindow::GetMenuBar()
nsMenuBarX* nsCocoaWindow::GetMenuBar()
{
return mMenuBar;
}
@ -1410,7 +1404,7 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
nsCocoaWindow* geckoWidget = [windowDelegate geckoWidget];
NS_ASSERTION(geckoWidget, "Window delegate not returning a gecko widget!");
nsIMenuBar* geckoMenuBar = geckoWidget->GetMenuBar();
nsMenuBarX* geckoMenuBar = geckoWidget->GetMenuBar();
if (geckoMenuBar) {
geckoMenuBar->Paint();
}
@ -1498,7 +1492,7 @@ NS_IMETHODIMP nsCocoaWindow::EndSecureKeyboardInput()
// app modally. If one of those is up then we want it to retain its menu bar.
if ([NSApp _isRunningAppModal])
return;
nsCOMPtr<nsIMenuBar> hiddenWindowMenuBar = MenuHelpersX::GetHiddenWindowMenuBar();
nsRefPtr<nsMenuBarX> hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar();
if (hiddenWindowMenuBar) {
// printf("painting hidden window menu bar due to window losing main status\n");
hiddenWindowMenuBar->Paint();

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

@ -1,240 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIMenu_h__
#define nsIMenu_h__
#include "nsISupports.h"
#include "nsStringFwd.h"
#include "nsEvent.h"
class nsIMenuBar;
class nsIMenu;
class nsIMenuItem;
class nsIContent;
class nsIWidget;
class nsMenuBarX;
// 9225136B-3F56-4CA3-92E0-623D5FB8356B
#define NS_IMENU_IID \
{ 0x9225136B, 0x3F56, 0x4CA3, \
{ 0x92, 0xE0, 0x62, 0x3D, 0x5F, 0xB8, 0x35, 0x6B } }
/**
* Menu widget
*/
class nsIMenu : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMENU_IID)
/**
* Creates the Menu
*
*/
NS_IMETHOD Create(nsISupports * aParent, const nsAString &aLabel, const nsAString &aAccessKey,
nsMenuBarX* aMenuBar, nsIContent* aNode) = 0;
/**
* Get the Menu's Parent. This addrefs.
*
*/
NS_IMETHOD GetParent(nsISupports *&aParent) = 0;
/**
* Get the Menu label
*
*/
NS_IMETHOD GetLabel(nsString &aText) = 0;
/**
* Set the Menu label
*
*/
NS_IMETHOD SetLabel(const nsAString &aText) = 0;
/**
* Get the Menu Access Key
*
*/
NS_IMETHOD GetAccessKey(nsString &aText) = 0;
/**
* Set the Menu Access Key
*
*/
NS_IMETHOD SetAccessKey(const nsAString &aText) = 0;
/**
* Set the Menu enabled state
*
*/
NS_IMETHOD SetEnabled(PRBool aIsEnabled) = 0;
/**
* Get the Menu enabled state
*
*/
NS_IMETHOD GetEnabled(PRBool* aIsEnabled) = 0;
/**
* Adds a Menu Item. Do not use outside of widget menu implementations.
* Add and modify menu items via DOM content.
*
*/
NS_IMETHOD AddItem(nsISupports* aItem) = 0;
/**
* Returns the number of visible menu items
* This includes separators. It does not include hidden items.
*
*/
NS_IMETHOD GetVisibleItemCount(PRUint32 &aCount) = 0;
/**
* Returns a Menu or Menu Item at a specified Index.
* This includes separators. It does not include hidden items.
*
*/
NS_IMETHOD GetVisibleItemAt(const PRUint32 aPos, nsISupports *& aMenuItem) = 0;
/**
* Returns the number of menu items
* This includes separators. It -does- include hidden items.
*
*/
NS_IMETHOD GetItemCount(PRUint32 &aCount) = 0;
/**
* Returns a Menu or Menu Item at a specified Index.
* This includes separators. It -does- include hidden items.
*
*/
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem) = 0;
/**
* Inserts a Menu Item at a specified Index
*
*/
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem) = 0;
/**
* Removes an Menu Item from a specified Index
*
*/
NS_IMETHOD RemoveItem(const PRUint32 aPos) = 0;
/**
* Removes all the Menu Items
*
*/
NS_IMETHOD RemoveAll() = 0;
/**
* Gets Native MenuHandle
*
*/
NS_IMETHOD GetNativeData(void** aData) = 0;
/**
* Sets Native MenuHandle
*
*/
NS_IMETHOD SetNativeData(void* aData) = 0;
/**
* Get menu content
*
*/
NS_IMETHOD GetMenuContent(nsIContent ** aMenuContent) = 0;
/**
* Enable/disable native widget for a particular nsIMenuItem
*
*/
NS_IMETHOD ChangeNativeEnabledStatusForMenuItem(nsIMenuItem* aMenuItem,
PRBool aEnabled) = 0;
/**
* Retrieve the native menu and the index of the item within that menu.
*
*/
NS_IMETHOD GetMenuRefAndItemIndexForMenuItem(nsISupports* aMenuItem,
void** aMenuRef,
PRUint16* aMenuItemIndex) = 0;
/**
* Sets an appropriate icon for the menu.
*
*/
NS_IMETHOD SetupIcon() = 0;
/**
* Menu has been selected
*
*/
virtual nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent) = 0;
/**
* Menu has been deselected
*
*/
virtual void MenuDeselected(const nsMenuEvent & aMenuEvent) = 0;
/**
* Construct menu
*
*/
virtual void MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, void * aMenuNode) = 0;
/**
* Destruct menu
*
*/
virtual void MenuDestruct(const nsMenuEvent & aMenuEvent) = 0;
/**
* Set rebuild
*
*/
virtual void SetRebuild(PRBool aMenuEvent) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIMenu, NS_IMENU_IID)
#endif

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

@ -1,156 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIMenuItem_h__
#define nsIMenuItem_h__
#include "prtypes.h"
#include "nsISupports.h"
#include "nsString.h"
#include "nsIDOMElement.h"
// 33FA04E3-EAFE-4DD1-AFB3-B3BC8C712716
#define NS_IMENUITEM_IID \
{ 0x33FA04E3, 0xEAFE, 0x4DD1, \
{ 0xAF, 0xB3, 0xB3, 0xBC, 0x8C, 0x71, 0x27, 0x16 } }
class nsIMenu;
class nsIWidget;
class nsIContent;
class nsMenuBarX;
enum {
knsMenuItemNoModifier = 0,
knsMenuItemShiftModifier = (1 << 0),
knsMenuItemAltModifier = (1 << 1),
knsMenuItemControlModifier = (1 << 2),
knsMenuItemCommandModifier = (1 << 3)
};
/**
* MenuItem widget
*/
class nsIMenuItem : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMENUITEM_IID)
enum EMenuItemType { eRegular = 0, eCheckbox, eRadio, eSeparator} ;
/**
* Creates the MenuItem
*
*/
NS_IMETHOD Create(nsIMenu* aParent, const nsString & aLabel, EMenuItemType aItemType,
nsMenuBarX* aMenuBar, nsIContent* aNode) = 0;
/**
* Get the MenuItem label
*
*/
NS_IMETHOD GetLabel(nsString &aText) = 0;
/**
* Get the Menu shortcut char
*
*/
NS_IMETHOD GetShortcutChar(nsString &aText) = 0;
/**
* Gets whether the item is enabled or disabled
*
*/
NS_IMETHOD GetEnabled(PRBool *aIsEnabled) = 0;
/**
* Sets whether the item is checked or not
*
*/
NS_IMETHOD SetChecked(PRBool aIsEnabled) = 0;
/**
* Gets whether the item is checked or not
*
*/
NS_IMETHOD GetChecked(PRBool *aIsEnabled) = 0;
/**
* Gets whether the item is a checkbox or radio
*
*/
NS_IMETHOD GetMenuItemType(EMenuItemType *aType) = 0;
/**
* Gets Native Menu Handle
*
*/
NS_IMETHOD GetNativeData(void*& aData) = 0;
/**
* Indicates whether it is a separator
*
*/
NS_IMETHOD IsSeparator(PRBool & aIsSep) = 0;
/**
* Executes the "cached" JavaScript Command
* @return NS_OK if the command was executed properly, otherwise an error code
*/
NS_IMETHOD DoCommand() = 0;
/**
* Sends a DOM event to the menu item's content node
* @return NS_OK if the event was sent properly, otherwise an error code
*/
NS_IMETHOD DispatchDOMEvent(const nsString &eventName, PRBool *preventDefaultCalled) = 0;
/**
* Sets an appropriate icon for the menu item.
*/
NS_IMETHOD SetupIcon() = 0;
/**
* Get GetMenuItemContent
*
*/
NS_IMETHOD GetMenuItemContent(nsIContent ** aMenuItemContent) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIMenuItem, NS_IMENUITEM_IID)
#endif

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

@ -39,35 +39,29 @@
#ifndef nsMenuBarX_h_
#define nsMenuBarX_h_
#include "nsIMenuBar.h"
#include "nsObjCExceptions.h"
#import <Cocoa/Cocoa.h>
#include "nsMenuBaseX.h"
#include "nsIMutationObserver.h"
#include "nsCOMArray.h"
#include "nsHashtable.h"
#include "nsWeakReference.h"
#include "nsIContent.h"
#include "nsINativeMenuService.h"
#include "nsAutoPtr.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
class nsIWidget;
class nsIDocument;
class nsIDOMNode;
class nsMenuX;
class nsMenuItemX;
class nsChangeObserver;
class nsIWidget;
class nsIContent;
class nsIDocument;
extern "C" MenuRef _NSGetCarbonMenu(NSMenu* aMenu);
PRBool NodeIsHiddenOrCollapsed(nsIContent* inContent);
namespace MenuHelpersX
// The native menu service for creating native menu bars.
class nsNativeMenuServiceX : public nsINativeMenuService
{
nsEventStatus DispatchCommandTo(nsIContent* aTargetContent);
NSString* CreateTruncatedCocoaLabel(const nsString& itemLabel);
PRUint8 GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute);
unsigned int MacModifiersForGeckoModifiers(PRUint8 geckoModifiers);
nsIMenuBar* GetHiddenWindowMenuBar();
NSMenuItem* GetStandardEditMenuItem();
}
public:
NS_DECL_ISUPPORTS
NS_IMETHOD CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode);
};
// Objective-C class used to allow us to have keyboard commands
@ -76,8 +70,8 @@ namespace MenuHelpersX
@interface GeckoNSMenu : NSMenu
{
}
- (BOOL)performKeyEquivalent:(NSEvent *)theEvent;
- (void)actOnKeyEquivalent:(NSEvent *)theEvent;
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
- (void)actOnKeyEquivalent:(NSEvent*)theEvent;
- (void)performMenuUserInterfaceEffectsForEvent:(NSEvent*)theEvent;
@end
@ -90,73 +84,59 @@ namespace MenuHelpersX
@end
//
// Native menu bar wrapper
//
class nsMenuBarX : public nsIMenuBar,
public nsIMutationObserver,
public nsSupportsWeakReference
// Once instantiated, this object lives until its DOM node or its parent window is destroyed.
// Do not hold references to this, they can become invalid any time the DOM node can be destroyed.
class nsMenuBarX : public nsMenuObjectX,
public nsIMutationObserver
{
public:
nsMenuBarX();
virtual ~nsMenuBarX();
nsMenuBarX();
virtual ~nsMenuBarX();
// |NSMenuItem|s target Objective-C objects
static NativeMenuItemTarget* sNativeEventTarget;
static nsMenuBarX* sLastGeckoMenuBarPainted;
NS_DECL_ISUPPORTS
static NativeMenuItemTarget* sNativeEventTarget;
static nsMenuBarX* sLastGeckoMenuBarPainted;
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER
// The following content nodes have been removed from the menu system.
// We save them here for use in command handling.
nsCOMPtr<nsIContent> mAboutItemContent;
nsCOMPtr<nsIContent> mPrefItemContent;
nsCOMPtr<nsIContent> mQuitItemContent;
// nsIMenuBar Methods
NS_IMETHOD Create(nsIWidget * aParent);
NS_IMETHOD GetParent(nsIWidget *&aParent);
NS_IMETHOD SetParent(nsIWidget * aParent);
NS_IMETHOD AddMenu(nsIMenu * aMenu);
NS_IMETHOD GetMenuCount(PRUint32 &aCount);
NS_IMETHOD GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu);
NS_IMETHOD RemoveMenu(const PRUint32 aCount);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD Paint();
NS_IMETHOD SetNativeData(void* aData);
NS_IMETHOD MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, void * aMenuNode);
NS_DECL_ISUPPORTS
NS_DECL_NSIMUTATIONOBSERVER
PRUint32 RegisterForCommand(nsIMenuItem* aItem);
void UnregisterCommand(PRUint32 aCommandID);
nsIMenuItem* GetMenuItemForCommandID(PRUint32 inCommandID);
// nsMenuObjectX
void* NativeData() {return (void*)mRootMenu;}
nsMenuObjectTypeX MenuObjectType() {return eMenuBarObjectType;}
void RegisterForContentChanges(nsIContent* aContent, nsChangeObserver* aMenuObject);
void UnregisterForContentChanges(nsIContent* aContent);
nsChangeObserver* LookupContentChangeObserver(nsIContent* aContent);
// nsMenuBarX
nsresult Create(nsIWidget* aParent, nsIContent* aContent);
void SetParent(nsIWidget* aParent);
void RegisterForContentChanges(nsIContent* aContent, nsChangeObserver* aMenuObject);
void UnregisterForContentChanges(nsIContent* aContent);
PRUint32 RegisterForCommand(nsMenuItemX* aItem);
void UnregisterCommand(PRUint32 aCommandID);
PRUint32 GetMenuCount();
nsMenuX* GetMenuAt(PRUint32 aIndex);
nsMenuItemX* GetMenuItemForCommandID(PRUint32 inCommandID);
nsresult Paint();
nsCOMPtr<nsIContent> mAboutItemContent; // holds the content node for the about item that has
// been removed from the menubar
nsCOMPtr<nsIContent> mPrefItemContent; // as above, but for prefs
nsCOMPtr<nsIContent> mQuitItemContent; // as above, but for quit
protected:
// Make our menubar conform to Aqua UI guidelines
void AquifyMenuBar();
void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode);
nsresult AddMenu(nsMenuX* aMenu);
void RemoveMenu(PRUint32 aIndex);
nsChangeObserver* LookupContentChangeObserver(nsIContent* aContent);
void HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode);
void AquifyMenuBar();
NSMenuItem* CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString& nodeID, SEL action,
int tag, NativeMenuItemTarget* target);
nsresult CreateApplicationMenu(nsMenuX* inMenu);
// build the Application menu shared by all menu bars.
NSMenuItem* CreateNativeAppMenuItem(nsIMenu* inMenu, const nsAString& nodeID, SEL action,
int tag, NativeMenuItemTarget* target);
nsresult CreateApplicationMenu(nsIMenu* inMenu);
nsCOMArray<nsIMenu> mMenusArray; // holds refs
nsCOMPtr<nsIContent> mMenuBarContent; // menubar content node, strong ref
nsIWidget* mParent; // weak ref
PRBool mIsMenuBarAdded;
PRUint32 mCurrentCommandID; // unique command id (per menu-bar) to give to next item that asks
nsIDocument* mDocument; // pointer to document
GeckoNSMenu* mRootMenu; // root menu, representing entire menu bar
nsHashtable mObserverTable; // stores observers for content change notification
nsTArray< nsAutoPtr<nsMenuX> > mMenuArray;
nsIWidget* mParent; // [weak]
PRUint32 mCurrentCommandID; // unique command id (per menu-bar) to give to next item that asks
nsIDocument* mDocument; // pointer to document
GeckoNSMenu* mRootMenu; // root menu, representing entire menu bar
nsHashtable mObserverTable; // stores observers for content change notification
};
#endif // nsMenuBarX_h_

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

@ -36,37 +36,28 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsIComponentManager.h"
#include "nsINameSpaceManager.h"
#include "nsIMenu.h"
#include "nsIMenuItem.h"
#include "nsIContent.h"
#include "nsMenuBarX.h"
#include "nsMenuX.h"
#include "nsChildView.h"
#include "nsMenuItemX.h"
#include "nsMenuUtilsX.h"
#include "nsCocoaUtils.h"
#include "nsCocoaWindow.h"
#include "nsISupports.h"
#include "nsIWidget.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIStringBundle.h"
#include "nsIDocument.h"
#include "nsIMutationObserver.h"
#include "nsIDOMDocument.h"
#include "nsWidgetAtoms.h"
#include "nsGUIEvent.h"
#include "nsObjCExceptions.h"
#include "nsHashtable.h"
#include "nsThreadUtils.h"
// CIDs
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuCID, NS_MENU_CID);
#include "nsIContent.h"
#include "nsIWidget.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
NS_IMPL_ISUPPORTS3(nsMenuBarX, nsIMenuBar, nsIMutationObserver, nsISupportsWeakReference)
NS_IMPL_ISUPPORTS1(nsMenuBarX, nsIMutationObserver)
NativeMenuItemTarget* nsMenuBarX::sNativeEventTarget = nil;
nsMenuBarX* nsMenuBarX::sLastGeckoMenuBarPainted = nsnull;
@ -92,18 +83,22 @@ enum {
};
PRBool NodeIsHiddenOrCollapsed(nsIContent* inContent)
NS_IMPL_ISUPPORTS1(nsNativeMenuServiceX, nsINativeMenuService)
NS_IMETHODIMP nsNativeMenuServiceX::CreateNativeMenuBar(nsIWidget* aParent, nsIContent* aMenuBarNode)
{
return (inContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::hidden,
nsWidgetAtoms::_true, eCaseMatters) ||
inContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::collapsed,
nsWidgetAtoms::_true, eCaseMatters));
NS_ASSERTION(NS_IsMainThread(), "Attempting to create native menu bar on wrong thread!");
nsRefPtr<nsMenuBarX> mb = new nsMenuBarX();
if (!mb)
return NS_ERROR_OUT_OF_MEMORY;
return mb->Create(aParent, aMenuBarNode);
}
nsMenuBarX::nsMenuBarX()
: mParent(nsnull),
mIsMenuBarAdded(PR_FALSE),
mCurrentCommandID(eCommand_ID_Last),
mDocument(nsnull)
{
@ -122,8 +117,6 @@ nsMenuBarX::~nsMenuBarX()
if (nsMenuBarX::sLastGeckoMenuBarPainted == this)
nsMenuBarX::sLastGeckoMenuBarPainted = nsnull;
mMenusArray.Clear(); // release all menus
// the quit/pref items of a random window might have been used if there was no
// hidden window, thus we need to invalidate the weak references.
if (sAboutItemContent == mAboutItemContent)
@ -136,18 +129,174 @@ nsMenuBarX::~nsMenuBarX()
// make sure we unregister ourselves as a document observer
if (mDocument)
mDocument->RemoveMutationObserver(this);
// We have to manually clear the array here because clearing causes menu items
// to call back into the menu bar to unregister themselves. We don't want to
// depend on member variable ordering to ensure that the array gets cleared
// before the registration hash table is destroyed.
mMenuArray.Clear();
[mRootMenu release];
NS_OBJC_END_TRY_ABORT_BLOCK;
}
// Do what's necessary to conform to the Aqua guidelines for menus.
void
nsMenuBarX::AquifyMenuBar()
nsresult nsMenuBarX::Create(nsIWidget* aParent, nsIContent* aContent)
{
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(mMenuBarContent->GetDocument()));
if (!aParent || !aContent)
return NS_ERROR_INVALID_ARG;
mParent = aParent;
mContent = aContent;
AquifyMenuBar();
nsIDocument* doc = aContent->GetOwnerDoc();
if (!doc)
return NS_ERROR_FAILURE;
doc->AddMutationObserver(this);
mDocument = doc;
PRUint32 count = mContent->GetChildCount();
for (PRUint32 i = 0; i < count; i++) {
nsIContent *menuContent = mContent->GetChildAt(i);
if (menuContent) {
if (menuContent->Tag() == nsWidgetAtoms::menu &&
menuContent->IsNodeOfType(nsINode::eXUL)) {
nsAutoString menuName;
menuContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::label, menuName);
nsMenuX* newMenu = new nsMenuX();
if (newMenu) {
nsresult rv = newMenu->Create(this, menuName, this, menuContent);
if (NS_SUCCEEDED(rv))
AddMenu(newMenu);
else
delete newMenu;
}
}
}
}
// Give this to the parent window. The parent takes ownership.
return mParent->SetMenuBar(this);
}
PRUint32 nsMenuBarX::GetMenuCount()
{
return mMenuArray.Length();
}
nsresult nsMenuBarX::AddMenu(nsMenuX* aMenu)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// If we haven't created a global Application menu yet, do it.
if (!sApplicationMenu) {
nsresult rv = NS_OK; // avoid warning about rv being unused
rv = CreateApplicationMenu(aMenu);
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create Application menu");
// Hook the new Application menu up to the menu bar.
NSMenu* mainMenu = [NSApp mainMenu];
NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!");
[[mainMenu itemAtIndex:0] setSubmenu:sApplicationMenu];
}
// keep track of all added menus
mMenuArray.AppendElement(aMenu); // owner
NSMenu* nativeMenu = (NSMenu*)aMenu->NativeData();
nsIContent* menuContent = aMenu->Content();
if (menuContent->GetChildCount() > 0 &&
!nsMenuUtilsX::NodeIsHiddenOrCollapsed(menuContent)) {
NSMenuItem* newMenuItem = [[[NSMenuItem alloc] initWithTitle:[nativeMenu title] action:NULL keyEquivalent:@""] autorelease];
[mRootMenu addItem:newMenuItem];
[newMenuItem setSubmenu:nativeMenu];
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
void nsMenuBarX::RemoveMenu(PRUint32 aIndex)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
NS_ASSERTION(aIndex < mMenuArray.Length(), "Attempting submenu removal with bad index!");
// Our native menu and our internal menu object array might be out of sync.
// This happens, for example, when a submenu is hidden. Because of this we
// should not assume that a native submenu is hooked up.
[mRootMenu removeItem:(mMenuArray[aIndex]->NativeMenuItem())];
mMenuArray.RemoveElementAt(aIndex);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
nsMenuX* nsMenuBarX::GetMenuAt(PRUint32 aIndex)
{
if (mMenuArray.Length() <= aIndex) {
NS_ERROR("Requesting menu at invalid index!");
return NULL;
}
return mMenuArray[aIndex];
}
nsresult nsMenuBarX::Paint()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NSMenu* mainMenu = [NSApp mainMenu];
NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!");
// Swap out first item into incoming menu bar. We have to keep the same menu item for the
// Application menu and its submenu is global so we keep passing it along.
NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain];
[mainMenu removeItemAtIndex:0];
[mRootMenu insertItem:firstMenuItem atIndex:0];
[firstMenuItem release];
// Set menu bar and event target.
[NSApp setMainMenu:mRootMenu];
nsMenuBarX::sLastGeckoMenuBarPainted = this;
gSomeMenuBarPainted = YES;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// Hide the item in the menu by setting the 'hidden' attribute. Returns it in |outHiddenNode| so
// the caller can hang onto it if they so choose. It is acceptable to pass nsull
// for |outHiddenNode| if the caller doesn't care about the hidden node.
void nsMenuBarX::HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode)
{
nsCOMPtr<nsIDOMElement> menuItem;
inDoc->GetElementById(inID, getter_AddRefs(menuItem));
nsCOMPtr<nsIContent> menuContent(do_QueryInterface(menuItem));
if (menuContent) {
menuContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::hidden, NS_LITERAL_STRING("true"), PR_FALSE);
if (outHiddenNode) {
*outHiddenNode = menuContent.get();
NS_IF_ADDREF(*outHiddenNode);
}
}
}
// Do what is necessary to conform to the Aqua guidelines for menus.
void nsMenuBarX::AquifyMenuBar()
{
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(mContent->GetDocument()));
if (domDoc) {
// remove the "About..." item and its separator
HideItem(domDoc, NS_LITERAL_STRING("aboutSeparator"), nsnull);
@ -177,145 +326,13 @@ nsMenuBarX::AquifyMenuBar()
}
// Hide the item in the menu by setting the 'hidden' attribute. Returns it in |outHiddenNode| so
// the caller can hang onto it if they so choose. It is acceptable to pass nsull
// for |outHiddenNode| if the caller doesn't care about the hidden node.
void
nsMenuBarX::HideItem(nsIDOMDocument* inDoc, const nsAString & inID, nsIContent** outHiddenNode)
{
nsCOMPtr<nsIDOMElement> menuItem;
inDoc->GetElementById(inID, getter_AddRefs(menuItem));
nsCOMPtr<nsIContent> menuContent(do_QueryInterface(menuItem));
if (menuContent) {
menuContent->SetAttr(kNameSpaceID_None, nsWidgetAtoms::hidden, NS_LITERAL_STRING("true"), PR_FALSE);
if (outHiddenNode) {
*outHiddenNode = menuContent.get();
NS_IF_ADDREF(*outHiddenNode);
}
}
}
NS_IMETHODIMP
nsMenuBarX::MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget* aParentWindow, void * aMenubarNode)
{
nsIDOMNode* domNode = static_cast<nsIDOMNode*>(aMenubarNode);
mMenuBarContent = do_QueryInterface(domNode); // strong ref
NS_ASSERTION(mMenuBarContent, "No content specified for this menubar");
if (!mMenuBarContent)
return NS_ERROR_FAILURE;
SetParent(aParentWindow);
AquifyMenuBar();
nsCOMPtr<nsIDOMDocument> domDoc;
domNode->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
if (!doc)
return NS_ERROR_FAILURE;
doc->AddMutationObserver(this);
mDocument = doc;
PRUint32 count = mMenuBarContent->GetChildCount();
for (PRUint32 i = 0; i < count; i++) {
nsIContent *menu = mMenuBarContent->GetChildAt(i);
if (menu) {
if (menu->Tag() == nsWidgetAtoms::menu &&
menu->IsNodeOfType(nsINode::eXUL)) {
nsAutoString menuName;
nsAutoString menuAccessKey(NS_LITERAL_STRING(" "));
menu->GetAttr(kNameSpaceID_None, nsWidgetAtoms::label, menuName);
menu->GetAttr(kNameSpaceID_None, nsWidgetAtoms::accesskey, menuAccessKey);
// Create nsMenu, the menubar will own it
nsCOMPtr<nsIMenu> pnsMenu(do_CreateInstance(kMenuCID));
if (pnsMenu) {
pnsMenu->Create(static_cast<nsIMenuBar*>(this), menuName, menuAccessKey, this, menu);
AddMenu(pnsMenu);
}
}
}
}
// Give the aParentWindow this nsMenuBarX to hold onto.
// The parent takes ownership.
aParentWindow->SetMenuBar(this);
return NS_OK;
}
NS_IMETHODIMP nsMenuBarX::Create(nsIWidget *aParent)
{
SetParent(aParent);
return NS_OK;
}
NS_IMETHODIMP nsMenuBarX::GetParent(nsIWidget *&aParent)
{
NS_IF_ADDREF(aParent = mParent);
return NS_OK;
}
NS_IMETHODIMP nsMenuBarX::SetParent(nsIWidget *aParent)
{
mParent = aParent; // weak ref
return NS_OK;
}
NS_IMETHODIMP nsMenuBarX::AddMenu(nsIMenu * aMenu)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// If we haven't created a global Application menu yet, do it.
if (!sApplicationMenu) {
nsresult rv = NS_OK; // avoid warning about rv being unused
rv = CreateApplicationMenu(aMenu);
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create Application menu");
// Hook the new Application menu up to the menu bar.
NSMenu* mainMenu = [NSApp mainMenu];
NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!");
[[mainMenu itemAtIndex:0] setSubmenu:sApplicationMenu];
}
// keep track of all added menus
mMenusArray.AppendObject(aMenu); // owner
NSMenu* nativeMenu = NULL;
aMenu->GetNativeData((void**)&nativeMenu);
nsCOMPtr<nsIContent> menu;
aMenu->GetMenuContent(getter_AddRefs(menu));
if (menu->GetChildCount() > 0 &&
!NodeIsHiddenOrCollapsed(menu)) {
NSMenuItem* newMenuItem = [[[NSMenuItem alloc] initWithTitle:[nativeMenu title] action:NULL keyEquivalent:@""] autorelease];
[mRootMenu addItem:newMenuItem];
[newMenuItem setSubmenu:nativeMenu];
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
// for creating menu items destined for the Application menu
NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsIMenu* inMenu, const nsAString& nodeID, SEL action,
NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsMenuX* inMenu, const nsAString& nodeID, SEL action,
int tag, NativeMenuItemTarget* target)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
nsCOMPtr<nsIContent> menu;
inMenu->GetMenuContent(getter_AddRefs(menu));
if (!menu)
return nil;
nsCOMPtr<nsIDocument> doc = menu->GetDocument();
nsCOMPtr<nsIDocument> doc = inMenu->Content()->GetDocument();
if (!doc)
return nil;
@ -356,8 +373,8 @@ NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsIMenu* inMenu, const nsAString
// now grab the key equivalent modifiers
nsAutoString modifiersStr;
keyContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::modifiers, modifiersStr);
PRUint8 geckoModifiers = MenuHelpersX::GeckoModifiersForNodeAttribute(modifiersStr);
macKeyModifiers = MenuHelpersX::MacModifiersForGeckoModifiers(geckoModifiers);
PRUint8 geckoModifiers = nsMenuUtilsX::GeckoModifiersForNodeAttribute(modifiersStr);
macKeyModifiers = nsMenuUtilsX::MacModifiersForGeckoModifiers(geckoModifiers);
}
}
// get the label into NSString-form
@ -382,8 +399,7 @@ NSMenuItem* nsMenuBarX::CreateNativeAppMenuItem(nsIMenu* inMenu, const nsAString
// build the Application menu shared by all menu bars
nsresult
nsMenuBarX::CreateApplicationMenu(nsIMenu* inMenu)
nsresult nsMenuBarX::CreateApplicationMenu(nsMenuX* inMenu)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
@ -536,111 +552,33 @@ nsMenuBarX::CreateApplicationMenu(nsIMenu* inMenu)
}
NS_IMETHODIMP nsMenuBarX::GetMenuCount(PRUint32 &aCount)
void nsMenuBarX::SetParent(nsIWidget* aParent)
{
aCount = mMenusArray.Count();
return NS_OK;
mParent = aParent;
}
NS_IMETHODIMP nsMenuBarX::GetMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
{
aMenu = NULL;
nsCOMPtr<nsIMenu> menu = mMenusArray.ObjectAt(aCount);
if (!menu)
return NS_OK;
return CallQueryInterface(menu, &aMenu); // addref
}
NS_IMETHODIMP nsMenuBarX::InsertMenuAt(const PRUint32 aCount, nsIMenu *& aMenu)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMenuBarX::RemoveMenu(const PRUint32 aCount)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
mMenusArray.RemoveObjectAt(aCount);
[mRootMenu removeItemAtIndex:aCount];
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_IMETHODIMP nsMenuBarX::RemoveAll()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMenuBarX::GetNativeData(void *& aData)
{
aData = (void*)mRootMenu;
return NS_OK;
}
NS_IMETHODIMP nsMenuBarX::SetNativeData(void* aData)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMenuBarX::Paint()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
NSMenu* mainMenu = [NSApp mainMenu];
NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!");
// Swap out first item into incoming menu bar. We have to keep the same menu item for the
// Application menu and its submenu is global so we keep passing it along.
NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain];
[mainMenu removeItemAtIndex:0];
[mRootMenu insertItem:firstMenuItem atIndex:0];
[firstMenuItem release];
// Set menu bar and event target.
[NSApp setMainMenu:mRootMenu];
nsMenuBarX::sLastGeckoMenuBarPainted = this;
gSomeMenuBarPainted = YES;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
//
// nsIMutationObserver
//
void
nsMenuBarX::CharacterDataWillChange(nsIDocument * aDocument,
nsIContent * aContent,
CharacterDataChangeInfo * aInfo)
{
}
void
nsMenuBarX::CharacterDataChanged(nsIDocument * aDocument,
nsIContent * aContent,
CharacterDataChangeInfo * aInfo)
void nsMenuBarX::CharacterDataWillChange(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
{
}
void
nsMenuBarX::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
void nsMenuBarX::CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,
CharacterDataChangeInfo* aInfo)
{
if (aContainer != mMenuBarContent) {
}
void nsMenuBarX::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
if (aContainer != mContent) {
nsChangeObserver* obs = LookupContentChangeObserver(aContainer);
if (obs)
obs->ObserveContentInserted(aDocument, aContainer, aNewIndexInContainer);
@ -656,17 +594,15 @@ nsMenuBarX::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
}
void
nsMenuBarX::NodeWillBeDestroyed(const nsINode * aNode)
void nsMenuBarX::NodeWillBeDestroyed(const nsINode * aNode)
{
mDocument = nsnull;
}
void
nsMenuBarX::AttributeChanged(nsIDocument * aDocument, nsIContent * aContent,
PRInt32 aNameSpaceID, nsIAtom * aAttribute,
PRInt32 aModType, PRUint32 aStateMask)
void nsMenuBarX::AttributeChanged(nsIDocument * aDocument, nsIContent * aContent,
PRInt32 aNameSpaceID, nsIAtom * aAttribute,
PRInt32 aModType, PRUint32 aStateMask)
{
// lookup and dispatch to registered thang
nsChangeObserver* obs = LookupContentChangeObserver(aContent);
@ -675,11 +611,10 @@ nsMenuBarX::AttributeChanged(nsIDocument * aDocument, nsIContent * aContent,
}
void
nsMenuBarX::ContentRemoved(nsIDocument * aDocument, nsIContent * aContainer,
nsIContent * aChild, PRInt32 aIndexInContainer)
void nsMenuBarX::ContentRemoved(nsIDocument * aDocument, nsIContent * aContainer,
nsIContent * aChild, PRInt32 aIndexInContainer)
{
if (aContainer == mMenuBarContent) {
if (aContainer == mContent) {
UnregisterForContentChanges(aChild);
RemoveMenu(aIndexInContainer);
}
@ -700,11 +635,10 @@ nsMenuBarX::ContentRemoved(nsIDocument * aDocument, nsIContent * aContainer,
}
void
nsMenuBarX::ContentInserted(nsIDocument * aDocument, nsIContent * aContainer,
nsIContent * aChild, PRInt32 aIndexInContainer)
void nsMenuBarX::ContentInserted(nsIDocument * aDocument, nsIContent * aContainer,
nsIContent * aChild, PRInt32 aIndexInContainer)
{
if (aContainer != mMenuBarContent) {
if (aContainer != mContent) {
nsChangeObserver* obs = LookupContentChangeObserver(aContainer);
if (obs)
obs->ObserveContentInserted(aDocument, aChild, aIndexInContainer);
@ -720,8 +654,7 @@ nsMenuBarX::ContentInserted(nsIDocument * aDocument, nsIContent * aContainer,
}
void
nsMenuBarX::ParentChainChanged(nsIContent *aContent)
void nsMenuBarX::ParentChainChanged(nsIContent *aContent)
{
}
@ -730,24 +663,21 @@ nsMenuBarX::ParentChainChanged(nsIContent *aContent)
// lifetime of all these items is bounded by the lifetime of the menubar. No need to add
// any more strong refs to the picture because the containment hierarchy already uses
// strong refs.
void
nsMenuBarX::RegisterForContentChanges(nsIContent *aContent, nsChangeObserver *aMenuObject)
void nsMenuBarX::RegisterForContentChanges(nsIContent *aContent, nsChangeObserver *aMenuObject)
{
nsVoidKey key(aContent);
mObserverTable.Put(&key, aMenuObject);
}
void
nsMenuBarX::UnregisterForContentChanges(nsIContent *aContent)
void nsMenuBarX::UnregisterForContentChanges(nsIContent *aContent)
{
nsVoidKey key(aContent);
mObserverTable.Remove(&key);
}
nsChangeObserver*
nsMenuBarX::LookupContentChangeObserver(nsIContent* aContent)
nsChangeObserver* nsMenuBarX::LookupContentChangeObserver(nsIContent* aContent)
{
nsVoidKey key(aContent);
return reinterpret_cast<nsChangeObserver*>(mObserverTable.Get(&key));
@ -756,8 +686,7 @@ nsMenuBarX::LookupContentChangeObserver(nsIContent* aContent)
// 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.
PRUint32
nsMenuBarX::RegisterForCommand(nsIMenuItem* inMenuItem)
PRUint32 nsMenuBarX::RegisterForCommand(nsMenuItemX* inMenuItem)
{
// 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,
@ -777,164 +706,17 @@ nsMenuBarX::RegisterForCommand(nsIMenuItem* inMenuItem)
// Removes the mapping between the given 4-character command ID
// and its associated menu item.
void
nsMenuBarX::UnregisterCommand(PRUint32 inCommandID)
void nsMenuBarX::UnregisterCommand(PRUint32 inCommandID)
{
nsPRUint32Key key(inCommandID);
mObserverTable.Remove(&key);
}
nsIMenuItem*
nsMenuBarX::GetMenuItemForCommandID(PRUint32 inCommandID)
nsMenuItemX* nsMenuBarX::GetMenuItemForCommandID(PRUint32 inCommandID)
{
nsPRUint32Key key(inCommandID);
return reinterpret_cast<nsIMenuItem*>(mObserverTable.Get(&key));
}
nsEventStatus
MenuHelpersX::DispatchCommandTo(nsIContent* aTargetContent)
{
NS_PRECONDITION(aTargetContent, "null ptr");
nsEventStatus status = nsEventStatus_eConsumeNoDefault;
nsXULCommandEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull);
// FIXME: Should probably figure out how to init this with the actual
// pressed keys, but this is a big old edge case anyway. -dwh
aTargetContent->DispatchDOMEvent(&event, nsnull, nsnull, &status);
return status;
}
NSString* MenuHelpersX::CreateTruncatedCocoaLabel(const nsString& itemLabel)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
// ::TruncateThemeText() doesn't take the number of characters to truncate to, it takes a pixel with
// to fit the string in. Ugh. I talked it over with sfraser and we couldn't come up with an
// easy way to compute what this should be given the system font, etc, so we're just going
// to hard code it to something reasonable and bigger fonts will just have to deal.
const short kMaxItemPixelWidth = 300;
NSMutableString *label = [[NSMutableString stringWithCharacters:itemLabel.get() length:itemLabel.Length()] retain];
::TruncateThemeText((CFMutableStringRef)label, kThemeMenuItemFont, kThemeStateActive, kMaxItemPixelWidth, truncMiddle, NULL);
return label; // caller releases
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
PRUint8 MenuHelpersX::GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute)
{
PRUint8 modifiers = knsMenuItemNoModifier;
char* str = ToNewCString(modifiersAttribute);
char* newStr;
char* token = nsCRT::strtok(str, ", \t", &newStr);
while (token != NULL) {
if (PL_strcmp(token, "shift") == 0)
modifiers |= knsMenuItemShiftModifier;
else if (PL_strcmp(token, "alt") == 0)
modifiers |= knsMenuItemAltModifier;
else if (PL_strcmp(token, "control") == 0)
modifiers |= knsMenuItemControlModifier;
else if ((PL_strcmp(token, "accel") == 0) ||
(PL_strcmp(token, "meta") == 0)) {
modifiers |= knsMenuItemCommandModifier;
}
token = nsCRT::strtok(newStr, ", \t", &newStr);
}
nsMemory::Free(str);
return modifiers;
}
unsigned int MenuHelpersX::MacModifiersForGeckoModifiers(PRUint8 geckoModifiers)
{
unsigned int macModifiers = 0;
if (geckoModifiers & knsMenuItemShiftModifier)
macModifiers |= NSShiftKeyMask;
if (geckoModifiers & knsMenuItemAltModifier)
macModifiers |= NSAlternateKeyMask;
if (geckoModifiers & knsMenuItemControlModifier)
macModifiers |= NSControlKeyMask;
if (geckoModifiers & knsMenuItemCommandModifier)
macModifiers |= NSCommandKeyMask;
return macModifiers;
}
nsIMenuBar* MenuHelpersX::GetHiddenWindowMenuBar()
{
nsIWidget* hiddenWindowWidgetNoCOMPtr = nsCocoaUtils::GetHiddenWindowWidget();
if (hiddenWindowWidgetNoCOMPtr)
return static_cast<nsCocoaWindow*>(hiddenWindowWidgetNoCOMPtr)->GetMenuBar();
else
return nsnull;
}
// It would be nice if we could localize these edit menu names.
static NSMenuItem* standardEditMenuItem = nil;
NSMenuItem* MenuHelpersX::GetStandardEditMenuItem()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (standardEditMenuItem)
return standardEditMenuItem;
NSMenuItem* standardEditMenuItem = [[NSMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:@""];
NSMenu* standardEditMenu = [[NSMenu alloc] initWithTitle:@"Edit"];
[standardEditMenuItem setSubmenu:standardEditMenu];
[standardEditMenu release];
// Add Undo
NSMenuItem* undoItem = [[NSMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:@"z"];
[standardEditMenu addItem:undoItem];
[undoItem release];
// Add Redo
NSMenuItem* redoItem = [[NSMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:@"Z"];
[standardEditMenu addItem:redoItem];
[redoItem release];
// Add separator
[standardEditMenu addItem:[NSMenuItem separatorItem]];
// Add Cut
NSMenuItem* cutItem = [[NSMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"];
[standardEditMenu addItem:cutItem];
[cutItem release];
// Add Copy
NSMenuItem* copyItem = [[NSMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"];
[standardEditMenu addItem:copyItem];
[copyItem release];
// Add Paste
NSMenuItem* pasteItem = [[NSMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"];
[standardEditMenu addItem:pasteItem];
[pasteItem release];
// Add Delete
NSMenuItem* deleteItem = [[NSMenuItem alloc] initWithTitle:@"Delete" action:@selector(delete:) keyEquivalent:@""];
[standardEditMenu addItem:deleteItem];
[deleteItem release];
// Add Select All
NSMenuItem* selectAllItem = [[NSMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:) keyEquivalent:@"a"];
[standardEditMenu addItem:selectAllItem];
[selectAllItem release];
standardEditMenuItem = standardEditMenuItem;
return standardEditMenuItem;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
return reinterpret_cast<nsMenuItemX*>(mObserverTable.Get(&key));
}
@ -1022,13 +804,13 @@ static BOOL gActOnSpecialCommands = YES;
nsIContent* mostSpecificContent = sAboutItemContent;
if (menuBar && menuBar->mAboutItemContent)
mostSpecificContent = menuBar->mAboutItemContent;
MenuHelpersX::DispatchCommandTo(mostSpecificContent);
nsMenuUtilsX::DispatchCommandTo(mostSpecificContent);
}
else if (tag == eCommand_ID_Prefs) {
nsIContent* mostSpecificContent = sPrefItemContent;
if (menuBar && menuBar->mPrefItemContent)
mostSpecificContent = menuBar->mPrefItemContent;
MenuHelpersX::DispatchCommandTo(mostSpecificContent);
nsMenuUtilsX::DispatchCommandTo(mostSpecificContent);
}
else if (tag == eCommand_ID_Quit) {
nsIContent* mostSpecificContent = sQuitItemContent;
@ -1038,7 +820,7 @@ static BOOL gActOnSpecialCommands = YES;
// message. If you want to stop a quit from happening, provide quit content and return
// the event as unhandled.
if (mostSpecificContent) {
MenuHelpersX::DispatchCommandTo(mostSpecificContent);
nsMenuUtilsX::DispatchCommandTo(mostSpecificContent);
}
else {
[NSApp terminate:nil];
@ -1061,12 +843,11 @@ static BOOL gActOnSpecialCommands = YES;
return;
// 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.
// that menu item.
if (menuBar) {
nsIMenuItem* content = menuBar->GetMenuItemForCommandID(static_cast<PRUint32>(tag));
if (content)
content->DoCommand();
nsMenuItemX* menuItem = menuBar->GetMenuItemForCommandID(static_cast<PRUint32>(tag));
if (menuItem)
menuItem->DoCommand();
}
NS_OBJC_END_TRY_ABORT_BLOCK;

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

@ -0,0 +1,68 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsMenuBaseX_h_
#define nsMenuBaseX_h_
#include "nsCOMPtr.h"
#include "nsIContent.h"
enum nsMenuObjectTypeX {
eMenuBarObjectType,
eSubmenuObjectType,
eMenuItemObjectType
};
// All menu objects subclass this.
// Menu bars are owned by their top-level nsIWidgets.
// All other objects are memory-managed based on the DOM.
// Content removal deletes them immediately and nothing else should.
// Do not attempt to hold strong references to them or delete them.
class nsMenuObjectX
{
public:
virtual ~nsMenuObjectX() { }
virtual nsMenuObjectTypeX MenuObjectType()=0;
virtual void* NativeData()=0;
nsIContent* Content() { return mContent; }
protected:
nsCOMPtr<nsIContent> mContent;
};
#endif // nsMenuBaseX_h_

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

@ -51,7 +51,7 @@
class nsIURI;
class nsIContent;
class imgIRequest;
class nsIMenu;
class nsMenuObjectX;
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
@ -60,10 +60,9 @@ class nsIMenu;
class nsMenuItemIconX : public imgIDecoderObserver
{
public:
nsMenuItemIconX(nsISupports* aMenuItem,
nsIMenu* aMenu,
nsIContent* aContent,
NSMenuItem* aNativeMenuItem);
nsMenuItemIconX(nsMenuObjectX* aMenuItem,
nsIContent* aContent,
NSMenuItem* aNativeMenuItem);
private:
~nsMenuItemIconX();
@ -86,10 +85,7 @@ public:
protected:
nsCOMPtr<nsIContent> mContent;
nsCOMPtr<imgIRequest> mIconRequest;
nsISupports* mMenuItem;
nsIMenu* mMenu;
MenuRef mMenuRef;
PRUint16 mMenuItemIndex;
nsMenuObjectX* mMenuObject;
PRPackedBool mLoadedIcon;
PRPackedBool mSetIcon;
NSMenuItem* mNativeMenuItem;

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

@ -45,8 +45,6 @@
#include "nsObjCExceptions.h"
#include "prmem.h"
#include "nsIMenu.h"
#include "nsIMenuItem.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsINameSpaceManager.h"
@ -64,6 +62,7 @@
#include "imgIRequest.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
#include "nsMenuItemX.h"
static const PRUint32 kIconWidth = 16;
static const PRUint32 kIconHeight = 16;
@ -83,15 +82,11 @@ PRAllocCGFree(void* aInfo, const void* aData, size_t aSize) {
NS_IMPL_ISUPPORTS2(nsMenuItemIconX, imgIContainerObserver, imgIDecoderObserver)
nsMenuItemIconX::nsMenuItemIconX(nsISupports* aMenuItem,
nsIMenu* aMenu,
nsIContent* aContent,
NSMenuItem* aNativeMenuItem)
nsMenuItemIconX::nsMenuItemIconX(nsMenuObjectX* aMenuItem,
nsIContent* aContent,
NSMenuItem* aNativeMenuItem)
: mContent(aContent)
, mMenuItem(aMenuItem)
, mMenu(aMenu)
, mMenuRef(NULL)
, mMenuItemIndex(0)
, mMenuObject(aMenuItem)
, mLoadedIcon(PR_FALSE)
, mSetIcon(PR_FALSE)
, mNativeMenuItem(aNativeMenuItem)
@ -112,18 +107,6 @@ nsMenuItemIconX::SetupIcon()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsresult rv;
if (!mMenuRef || !mMenuItemIndex) {
// These values are initialized here instead of in the constructor
// because they depend on the parent menu, mMenu, having inserted
// this object into its array of children. That can only happen after
// the object is constructed.
rv = mMenu->GetMenuRefAndItemIndexForMenuItem(mMenuItem,
(void**)&mMenuRef,
&mMenuItemIndex);
if (NS_FAILED(rv)) return rv;
}
// Still don't have one, then something is wrong, get out of here.
if (!mNativeMenuItem) {
NS_ERROR("No native menu item\n");
@ -131,7 +114,7 @@ nsMenuItemIconX::SetupIcon()
}
nsCOMPtr<nsIURI> iconURI;
rv = GetIconURI(getter_AddRefs(iconURI));
nsresult rv = GetIconURI(getter_AddRefs(iconURI));
if (NS_FAILED(rv)) {
// There is no icon for this menu item. An icon might have been set
// earlier. Clear it.
@ -155,15 +138,14 @@ nsMenuItemIconX::GetIconURI(nsIURI** aIconURI)
// The downside is that it's possible to get a menu item marked with a
// native checkmark and a checkmark for an icon. Head off that possibility
// by pretending that no icon exists if this is a checkable menu item.
nsCOMPtr<nsIMenuItem> menuItem = do_QueryInterface(mMenuItem);
if (menuItem) {
nsIMenuItem::EMenuItemType menuItemType;
menuItem->GetMenuItemType(&menuItemType);
if (menuItemType != nsIMenuItem::eRegular)
if (mMenuObject->MenuObjectType() == eMenuItemObjectType) {
nsMenuItemX* menuItem = static_cast<nsMenuItemX*>(mMenuObject);
if (menuItem->GetMenuItemType() != eRegularMenuItemType)
return NS_ERROR_FAILURE;
}
if (!mContent) return NS_ERROR_FAILURE;
if (!mContent)
return NS_ERROR_FAILURE;
// First, look at the content node's "image" attribute.
nsAutoString imageURIString;

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

@ -39,69 +39,68 @@
#ifndef nsMenuItemX_h_
#define nsMenuItemX_h_
#include "nsIMenuItem.h"
#include "nsString.h"
#include "nsMenuBaseX.h"
#include "nsChangeObserver.h"
#include "nsAutoPtr.h"
#import <Cocoa/Cocoa.h>
class nsIMenu;
class nsString;
class nsMenuItemIconX;
class nsMenuX;
class nsMenuBarX;
/**
* Native menu item wrapper
*/
enum {
knsMenuItemNoModifier = 0,
knsMenuItemShiftModifier = (1 << 0),
knsMenuItemAltModifier = (1 << 1),
knsMenuItemControlModifier = (1 << 2),
knsMenuItemCommandModifier = (1 << 3)
};
class nsMenuItemX : public nsIMenuItem,
enum EMenuItemType {
eRegularMenuItemType = 0,
eCheckboxMenuItemType,
eRadioMenuItemType,
eSeparatorMenuItemType
};
// Once instantiated, this object lives until its DOM node or its parent window is destroyed.
// Do not hold references to this, they can become invalid any time the DOM node can be destroyed.
class nsMenuItemX : public nsMenuObjectX,
public nsChangeObserver
{
public:
nsMenuItemX();
virtual ~nsMenuItemX();
// nsISupports
NS_DECL_ISUPPORTS
NS_DECL_CHANGEOBSERVER
// nsIMenuItem Methods
NS_IMETHOD Create(nsIMenu* aParent, const nsString & aLabel, EMenuItemType aItemType,
nsMenuBarX* aMenuBar, nsIContent* aNode);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD GetShortcutChar(nsString &aText);
NS_IMETHOD GetEnabled(PRBool *aIsEnabled);
NS_IMETHOD SetChecked(PRBool aIsEnabled);
NS_IMETHOD GetChecked(PRBool *aIsEnabled);
NS_IMETHOD GetMenuItemType(EMenuItemType *aIsCheckbox);
NS_IMETHOD GetNativeData(void*& aData);
NS_IMETHOD IsSeparator(PRBool & aIsSep);
// nsMenuObjectX
void* NativeData() {return (void*)mNativeMenuItem;}
nsMenuObjectTypeX MenuObjectType() {return eMenuItemObjectType;}
NS_IMETHOD DoCommand();
NS_IMETHOD DispatchDOMEvent(const nsString &eventName, PRBool *preventDefaultCalled);
NS_IMETHOD SetupIcon();
NS_IMETHOD GetMenuItemContent(nsIContent ** aMenuItemContent);
// nsMenuItemX
nsresult Create(nsMenuX* aParent, const nsString& aLabel, EMenuItemType aItemType,
nsMenuBarX* aMenuBar, nsIContent* aNode);
nsresult SetChecked(PRBool aIsChecked);
EMenuItemType GetMenuItemType();
void DoCommand();
nsresult DispatchDOMEvent(const nsString &eventName, PRBool* preventDefaultCalled);
void SetupIcon();
protected:
void UncheckRadioSiblings(nsIContent* inCheckedElement);
void SetKeyEquiv(PRUint8 aModifiers, const nsString &aText);
NSMenuItem* mNativeMenuItem; // strong ref, we own
nsString mLabel;
nsString mKeyEquivalent;
nsIMenu* mMenuParent; // weak, parent owns us
nsMenuBarX* mMenuBar; // weak
nsCOMPtr<nsIContent> mContent;
EMenuItemType mType;
NSMenuItem* mNativeMenuItem; // [strong]
nsMenuX* mMenuParent; // [weak]
nsMenuBarX* mMenuBar; // [weak]
nsCOMPtr<nsIContent> mCommandContent;
nsRefPtr<nsMenuItemIconX> mIcon;
PRUint8 mModifiers;
PRPackedBool mEnabled;
PRPackedBool mIsChecked;
EMenuItemType mType; // regular, checkbox, radio, or separator
PRBool mIsChecked;
};
#endif // nsMenuItemX_h_

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

@ -36,39 +36,37 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIContent.h"
#include "nsObjCExceptions.h"
#include "nsMenuBarX.h" // for MenuHelpers namespace
#include "nsMenuItemX.h"
#include "nsIMenu.h"
#include "nsIMenuBar.h"
#include "nsIWidget.h"
#include "nsINameSpaceManager.h"
#include "nsMenuBarX.h"
#include "nsMenuX.h"
#include "nsMenuItemIconX.h"
#include "nsMenuUtilsX.h"
#include "nsObjCExceptions.h"
#include "nsCOMPtr.h"
#include "nsWidgetAtoms.h"
#include "nsIServiceManager.h"
#include "nsGUIEvent.h"
#include "nsIContent.h"
#include "nsIWidget.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMDocumentEvent.h"
#include "nsMenuItemIconX.h"
#include "nsGUIEvent.h"
NS_IMPL_ISUPPORTS1(nsMenuItemX, nsIMenuItem)
#include "nsIDOMElement.h"
nsMenuItemX::nsMenuItemX()
{
mNativeMenuItem = nil;
mMenuParent = nsnull;
mMenuBar = nsnull;
mKeyEquivalent.AssignLiteral(" ");
mEnabled = PR_TRUE;
mIsChecked = PR_FALSE;
mType = eRegular;
mType = eRegularMenuItemType;
mNativeMenuItem = nil;
mMenuParent = nsnull;
mMenuBar = nsnull;
mIsChecked = PR_FALSE;
MOZ_COUNT_CTOR(nsMenuItemX);
}
@ -82,23 +80,24 @@ nsMenuItemX::~nsMenuItemX()
if (mCommandContent)
mMenuBar->UnregisterForContentChanges(mCommandContent);
MOZ_COUNT_DTOR(nsMenuItemX);
NS_OBJC_END_TRY_ABORT_BLOCK;
}
NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, EMenuItemType aItemType,
nsMenuBarX* aMenuBar, nsIContent* aNode)
nsresult nsMenuItemX::Create(nsMenuX* aParent, const nsString& aLabel, EMenuItemType aItemType,
nsMenuBarX* aMenuBar, nsIContent* aNode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
mContent = aNode; // addref
mMenuParent = aParent; // weak
mType = aItemType;
mMenuParent = aParent;
mContent = aNode;
// register for AttributeChanged messages
mMenuBar = aMenuBar;
NS_ASSERTION(mMenuBar, "No menu bar given, must have one");
NS_ASSERTION(mMenuBar, "No menu bar given, must have one!");
mMenuBar->RegisterForContentChanges(mContent, this);
nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(mContent->GetCurrentDoc()));
@ -120,26 +119,25 @@ NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, EMenuIt
}
}
}
// set up mEnabled based on command content if it exists, otherwise do it based
// decide enabled state based on command content if it exists, otherwise do it based
// on our own content
PRBool isEnabled;
if (mCommandContent)
mEnabled = !mCommandContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::disabled, nsWidgetAtoms::_true, eCaseMatters);
isEnabled = !mCommandContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::disabled, nsWidgetAtoms::_true, eCaseMatters);
else
mEnabled = !mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::disabled, nsWidgetAtoms::_true, eCaseMatters);
mLabel = aLabel;
isEnabled = !mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::disabled, nsWidgetAtoms::_true, eCaseMatters);
// set up the native menu item
if (mType == nsIMenuItem::eSeparator) {
if (mType == eSeparatorMenuItemType) {
mNativeMenuItem = [[NSMenuItem separatorItem] retain];
}
else {
NSString *newCocoaLabelString = MenuHelpersX::CreateTruncatedCocoaLabel(mLabel);
NSString *newCocoaLabelString = nsMenuUtilsX::CreateTruncatedCocoaLabel(aLabel);
mNativeMenuItem = [[NSMenuItem alloc] initWithTitle:newCocoaLabelString action:nil keyEquivalent:@""];
[newCocoaLabelString release];
[mNativeMenuItem setEnabled:(BOOL)mEnabled];
[mNativeMenuItem setEnabled:(BOOL)isEnabled];
SetChecked(mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::checked,
nsWidgetAtoms::_true, eCaseMatters));
@ -148,11 +146,9 @@ NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, EMenuIt
if (domDoc) {
nsAutoString keyValue;
mContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::key, keyValue);
if (!keyValue.IsEmpty()) {
nsCOMPtr<nsIDOMElement> keyElement;
domDoc->GetElementById(keyValue, getter_AddRefs(keyElement));
if (keyElement) {
nsCOMPtr<nsIContent> keyContent(do_QueryInterface(keyElement));
nsAutoString keyChar(NS_LITERAL_STRING(" "));
@ -160,7 +156,7 @@ NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, EMenuIt
nsAutoString modifiersStr;
keyContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::modifiers, modifiersStr);
PRUint8 modifiers = MenuHelpersX::GeckoModifiersForNodeAttribute(modifiersStr);
PRUint8 modifiers = nsMenuUtilsX::GeckoModifiersForNodeAttribute(modifiersStr);
SetKeyEquiv(modifiers, keyChar);
}
@ -168,31 +164,17 @@ NS_METHOD nsMenuItemX::Create(nsIMenu* aParent, const nsString & aLabel, EMenuIt
}
}
mIcon = new nsMenuItemIconX(static_cast<nsIMenuItem*>(this), mMenuParent, mContent, mNativeMenuItem);
mIcon = new nsMenuItemIconX(this, mContent, mNativeMenuItem);
if (!mIcon)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
NS_METHOD
nsMenuItemX::GetLabel(nsString &aText)
{
aText = mLabel;
return NS_OK;
}
NS_METHOD
nsMenuItemX::GetEnabled(PRBool *aIsEnabled)
{
*aIsEnabled = mEnabled;
return NS_OK;
}
NS_METHOD nsMenuItemX::SetChecked(PRBool aIsChecked)
nsresult nsMenuItemX::SetChecked(PRBool aIsChecked)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
@ -215,41 +197,19 @@ NS_METHOD nsMenuItemX::SetChecked(PRBool aIsChecked)
}
NS_METHOD nsMenuItemX::GetChecked(PRBool *aIsEnabled)
EMenuItemType nsMenuItemX::GetMenuItemType()
{
*aIsEnabled = mIsChecked;
return NS_OK;
}
NS_METHOD nsMenuItemX::GetMenuItemType(EMenuItemType *aType)
{
*aType = mType;
return NS_OK;
}
NS_METHOD nsMenuItemX::GetNativeData(void *& aData)
{
aData = mNativeMenuItem;
return NS_OK;
}
NS_METHOD nsMenuItemX::IsSeparator(PRBool & aIsSep)
{
aIsSep = (mType == nsIMenuItem::eSeparator);
return NS_OK;
return mType;
}
// Executes the "cached" javaScript command.
// Returns NS_OK if the command was executed properly, otherwise an error code.
NS_IMETHODIMP nsMenuItemX::DoCommand()
void nsMenuItemX::DoCommand()
{
// flip "checked" state if we're a checkbox menu, or an un-checked radio menu
if (mType == nsIMenuItem::eCheckbox ||
(mType == nsIMenuItem::eRadio && !mIsChecked)) {
if (mType == eCheckboxMenuItemType ||
(mType == eRadioMenuItemType && !mIsChecked)) {
if (!mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::autocheck,
nsWidgetAtoms::_false, eCaseMatters))
SetChecked(!mIsChecked);
@ -260,29 +220,28 @@ NS_IMETHODIMP nsMenuItemX::DoCommand()
nsXULCommandEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull);
mContent->DispatchDOMEvent(&event, nsnull, nsnull, &status);
return NS_OK;
}
NS_IMETHODIMP nsMenuItemX::DispatchDOMEvent(const nsString &eventName, PRBool *preventDefaultCalled)
nsresult nsMenuItemX::DispatchDOMEvent(const nsString &eventName, PRBool *preventDefaultCalled)
{
if (!mContent)
return NS_ERROR_FAILURE;
// get owner document for content
nsCOMPtr<nsIDocument> parentDoc = mContent->GetOwnerDoc();
if (!parentDoc) {
NS_WARNING("Failed to get owner nsIDocument for menu item content");
return NS_ERROR_FAILURE;
}
// get interface for creating DOM events from content owner document
nsCOMPtr<nsIDOMDocumentEvent> DOMEventFactory = do_QueryInterface(parentDoc);
if (!DOMEventFactory) {
NS_WARNING("Failed to QI parent nsIDocument to nsIDOMDocumentEvent");
return NS_ERROR_FAILURE;
}
// create DOM event
nsCOMPtr<nsIDOMEvent> event;
nsresult rv = DOMEventFactory->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
@ -291,11 +250,11 @@ NS_IMETHODIMP nsMenuItemX::DispatchDOMEvent(const nsString &eventName, PRBool *p
return rv;
}
event->InitEvent(eventName, PR_TRUE, PR_TRUE);
// mark DOM event as trusted
nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
privateEvent->SetTrusted(PR_TRUE);
// send DOM event
nsCOMPtr<nsIDOMEventTarget> eventTarget = do_QueryInterface(mContent);
rv = eventTarget->DispatchEvent(event, preventDefaultCalled);
@ -303,22 +262,14 @@ NS_IMETHODIMP nsMenuItemX::DispatchDOMEvent(const nsString &eventName, PRBool *p
NS_WARNING("Failed to send DOM event via nsIDOMEventTarget");
return rv;
}
return NS_OK;
}
NS_METHOD nsMenuItemX::GetShortcutChar(nsString &aText)
{
aText = mKeyEquivalent;
return NS_OK;
}
// Walk the sibling list looking for nodes with the same name and
// uncheck them all.
void
nsMenuItemX::UncheckRadioSiblings(nsIContent* inCheckedContent)
void nsMenuItemX::UncheckRadioSiblings(nsIContent* inCheckedContent)
{
nsAutoString myGroupName;
inCheckedContent->GetAttr(kNameSpaceID_None, nsWidgetAtoms::name, myGroupName);
@ -349,13 +300,11 @@ void nsMenuItemX::SetKeyEquiv(PRUint8 aModifiers, const nsString &aText)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
mModifiers = aModifiers;
unsigned int macModifiers = MenuHelpersX::MacModifiersForGeckoModifiers(mModifiers);
unsigned int macModifiers = nsMenuUtilsX::MacModifiersForGeckoModifiers(aModifiers);
[mNativeMenuItem setKeyEquivalentModifierMask:macModifiers];
mKeyEquivalent = aText;
NSString *keyEquivalent = [[NSString stringWithCharacters:(unichar*)mKeyEquivalent.get()
length:mKeyEquivalent.Length()] lowercaseString];
NSString *keyEquivalent = [[NSString stringWithCharacters:(unichar*)aText.get()
length:aText.Length()] lowercaseString];
if ([keyEquivalent isEqualToString:@" "])
[mNativeMenuItem setKeyEquivalent:@""];
else
@ -382,7 +331,7 @@ nsMenuItemX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aConten
if (aAttribute == nsWidgetAtoms::checked) {
// if we're a radio menu, uncheck our sibling radio items. No need to
// do any of this if we're just a normal check menu.
if (mType == nsIMenuItem::eRadio) {
if (mType == eRadioMenuItemType) {
if (mContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::checked,
nsWidgetAtoms::_true, eCaseMatters))
UncheckRadioSiblings(mContent);
@ -432,8 +381,7 @@ nsMenuItemX::ObserveAttributeChanged(nsIDocument *aDocument, nsIContent *aConten
}
void
nsMenuItemX::ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
void nsMenuItemX::ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
if (aChild == mCommandContent) {
mMenuBar->UnregisterForContentChanges(mCommandContent);
@ -444,27 +392,14 @@ nsMenuItemX::ObserveContentRemoved(nsIDocument *aDocument, nsIContent *aChild, P
}
void
nsMenuItemX::ObserveContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
void nsMenuItemX::ObserveContentInserted(nsIDocument *aDocument, nsIContent *aChild, PRInt32 aIndexInContainer)
{
mMenuParent->SetRebuild(PR_TRUE);
}
NS_IMETHODIMP
nsMenuItemX::SetupIcon()
void nsMenuItemX::SetupIcon()
{
if (!mIcon)
return NS_ERROR_OUT_OF_MEMORY;
return mIcon->SetupIcon();
}
NS_IMETHODIMP
nsMenuItemX::GetMenuItemContent(nsIContent ** aMenuItemContent)
{
NS_ENSURE_ARG_POINTER(aMenuItemContent);
NS_IF_ADDREF(*aMenuItemContent = mContent);
return NS_OK;
if (mIcon)
mIcon->SetupIcon();
}

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

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsMenuUtilsX_h_
#define nsMenuUtilsX_h_
#include "nscore.h"
#include "nsGUIEvent.h"
#import <Cocoa/Cocoa.h>
class nsIContent;
class nsString;
class nsMenuBarX;
// Namespace containing utility functions used in our native menu implementation.
namespace nsMenuUtilsX
{
nsEventStatus DispatchCommandTo(nsIContent* aTargetContent);
NSString* CreateTruncatedCocoaLabel(const nsString& itemLabel); // returned object is not retained
PRUint8 GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute);
unsigned int MacModifiersForGeckoModifiers(PRUint8 geckoModifiers);
nsMenuBarX* GetHiddenWindowMenuBar(); // returned object is not retained
NSMenuItem* GetStandardEditMenuItem(); // returned object is not retained
PRBool NodeIsHiddenOrCollapsed(nsIContent* inContent);
}
#endif // nsMenuUtilsX_h_

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

@ -0,0 +1,197 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Josh Aas <josh@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsMenuUtilsX.h"
#include "nsMenuBarX.h"
#include "nsMenuItemX.h"
#include "nsObjCExceptions.h"
#include "nsCocoaUtils.h"
#include "nsCocoaWindow.h"
#include "nsWidgetAtoms.h"
#import <Carbon/Carbon.h>
nsEventStatus nsMenuUtilsX::DispatchCommandTo(nsIContent* aTargetContent)
{
NS_PRECONDITION(aTargetContent, "null ptr");
nsEventStatus status = nsEventStatus_eConsumeNoDefault;
nsXULCommandEvent event(PR_TRUE, NS_XUL_COMMAND, nsnull);
// FIXME: Should probably figure out how to init this with the actual
// pressed keys, but this is a big old edge case anyway. -dwh
aTargetContent->DispatchDOMEvent(&event, nsnull, nsnull, &status);
return status;
}
NSString* nsMenuUtilsX::CreateTruncatedCocoaLabel(const nsString& itemLabel)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
// ::TruncateThemeText() doesn't take the number of characters to truncate to, it takes a pixel with
// to fit the string in. Ugh. I talked it over with sfraser and we couldn't come up with an
// easy way to compute what this should be given the system font, etc, so we're just going
// to hard code it to something reasonable and bigger fonts will just have to deal.
const short kMaxItemPixelWidth = 300;
NSMutableString *label = [[NSMutableString stringWithCharacters:itemLabel.get() length:itemLabel.Length()] retain];
::TruncateThemeText((CFMutableStringRef)label, kThemeMenuItemFont, kThemeStateActive, kMaxItemPixelWidth, truncMiddle, NULL);
return label; // caller releases
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
PRUint8 nsMenuUtilsX::GeckoModifiersForNodeAttribute(const nsString& modifiersAttribute)
{
PRUint8 modifiers = knsMenuItemNoModifier;
char* str = ToNewCString(modifiersAttribute);
char* newStr;
char* token = strtok_r(str, ", \t", &newStr);
while (token != NULL) {
if (strcmp(token, "shift") == 0)
modifiers |= knsMenuItemShiftModifier;
else if (strcmp(token, "alt") == 0)
modifiers |= knsMenuItemAltModifier;
else if (strcmp(token, "control") == 0)
modifiers |= knsMenuItemControlModifier;
else if ((strcmp(token, "accel") == 0) ||
(strcmp(token, "meta") == 0)) {
modifiers |= knsMenuItemCommandModifier;
}
token = strtok_r(newStr, ", \t", &newStr);
}
free(str);
return modifiers;
}
unsigned int nsMenuUtilsX::MacModifiersForGeckoModifiers(PRUint8 geckoModifiers)
{
unsigned int macModifiers = 0;
if (geckoModifiers & knsMenuItemShiftModifier)
macModifiers |= NSShiftKeyMask;
if (geckoModifiers & knsMenuItemAltModifier)
macModifiers |= NSAlternateKeyMask;
if (geckoModifiers & knsMenuItemControlModifier)
macModifiers |= NSControlKeyMask;
if (geckoModifiers & knsMenuItemCommandModifier)
macModifiers |= NSCommandKeyMask;
return macModifiers;
}
nsMenuBarX* nsMenuUtilsX::GetHiddenWindowMenuBar()
{
nsIWidget* hiddenWindowWidgetNoCOMPtr = nsCocoaUtils::GetHiddenWindowWidget();
if (hiddenWindowWidgetNoCOMPtr)
return static_cast<nsCocoaWindow*>(hiddenWindowWidgetNoCOMPtr)->GetMenuBar();
else
return nsnull;
}
// It would be nice if we could localize these edit menu names.
static NSMenuItem* standardEditMenuItem = nil;
NSMenuItem* nsMenuUtilsX::GetStandardEditMenuItem()
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
if (standardEditMenuItem)
return standardEditMenuItem;
standardEditMenuItem = [[NSMenuItem alloc] initWithTitle:@"Edit" action:nil keyEquivalent:@""];
NSMenu* standardEditMenu = [[NSMenu alloc] initWithTitle:@"Edit"];
[standardEditMenuItem setSubmenu:standardEditMenu];
[standardEditMenu release];
// Add Undo
NSMenuItem* undoItem = [[NSMenuItem alloc] initWithTitle:@"Undo" action:@selector(undo:) keyEquivalent:@"z"];
[standardEditMenu addItem:undoItem];
[undoItem release];
// Add Redo
NSMenuItem* redoItem = [[NSMenuItem alloc] initWithTitle:@"Redo" action:@selector(redo:) keyEquivalent:@"Z"];
[standardEditMenu addItem:redoItem];
[redoItem release];
// Add separator
[standardEditMenu addItem:[NSMenuItem separatorItem]];
// Add Cut
NSMenuItem* cutItem = [[NSMenuItem alloc] initWithTitle:@"Cut" action:@selector(cut:) keyEquivalent:@"x"];
[standardEditMenu addItem:cutItem];
[cutItem release];
// Add Copy
NSMenuItem* copyItem = [[NSMenuItem alloc] initWithTitle:@"Copy" action:@selector(copy:) keyEquivalent:@"c"];
[standardEditMenu addItem:copyItem];
[copyItem release];
// Add Paste
NSMenuItem* pasteItem = [[NSMenuItem alloc] initWithTitle:@"Paste" action:@selector(paste:) keyEquivalent:@"v"];
[standardEditMenu addItem:pasteItem];
[pasteItem release];
// Add Delete
NSMenuItem* deleteItem = [[NSMenuItem alloc] initWithTitle:@"Delete" action:@selector(delete:) keyEquivalent:@""];
[standardEditMenu addItem:deleteItem];
[deleteItem release];
// Add Select All
NSMenuItem* selectAllItem = [[NSMenuItem alloc] initWithTitle:@"Select All" action:@selector(selectAll:) keyEquivalent:@"a"];
[standardEditMenu addItem:selectAllItem];
[selectAllItem release];
return standardEditMenuItem;
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
}
PRBool nsMenuUtilsX::NodeIsHiddenOrCollapsed(nsIContent* inContent)
{
return (inContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::hidden,
nsWidgetAtoms::_true, eCaseMatters) ||
inContent->AttrValueIs(kNameSpaceID_None, nsWidgetAtoms::collapsed,
nsWidgetAtoms::_true, eCaseMatters));
}

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

@ -39,19 +39,19 @@
#ifndef nsMenuX_h_
#define nsMenuX_h_
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
#include "nsIMenu.h"
#include "nsChangeObserver.h"
#include "nsMenuBarX.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
#include "nsMenuBaseX.h"
#include "nsMenuBarX.h"
#include "nsCOMPtr.h"
#include "nsChangeObserver.h"
#include "nsAutoPtr.h"
class nsIMenuBar;
class nsMenuX;
class nsMenuItemIconX;
class nsMenuItemX;
class nsIWidget;
// MenuDelegate is used to receive Cocoa notifications for
@ -66,99 +66,71 @@ class nsMenuItemIconX;
@end
class nsMenuX : public nsIMenu,
// Once instantiated, this object lives until its DOM node or its parent window is destroyed.
// Do not hold references to this, they can become invalid any time the DOM node can be destroyed.
class nsMenuX : public nsMenuObjectX,
public nsChangeObserver
{
public:
nsMenuX();
virtual ~nsMenuX();
nsMenuX();
virtual ~nsMenuX();
// If > 0, the OS is indexing all the app's menus (triggered by opening
// Help menu on Leopard and higher). There are some things that are
// unsafe to do while this is happening.
static PRInt32 sIndexingMenuLevel;
// If > 0, the OS is indexing all the app's menus (triggered by opening
// Help menu on Leopard and higher). There are some things that are
// unsafe to do while this is happening.
static PRInt32 sIndexingMenuLevel;
NS_DECL_ISUPPORTS
NS_DECL_CHANGEOBSERVER
NS_DECL_CHANGEOBSERVER
id GetNativeMenuItem();
// nsMenuObjectX
void* NativeData() {return (void*)mMacMenu;}
nsMenuObjectTypeX MenuObjectType() {return eSubmenuObjectType;}
// nsIMenu Methods
NS_IMETHOD Create(nsISupports * aParent, const nsAString &aLabel, const nsAString &aAccessKey,
nsMenuBarX* aMenuBar, nsIContent* aNode);
NS_IMETHOD GetParent(nsISupports *&aParent);
NS_IMETHOD GetLabel(nsString &aText);
NS_IMETHOD SetLabel(const nsAString &aText);
NS_IMETHOD GetAccessKey(nsString &aText);
NS_IMETHOD SetAccessKey(const nsAString &aText);
NS_IMETHOD AddItem(nsISupports* aText);
NS_IMETHOD GetItemCount(PRUint32 &aCount);
NS_IMETHOD GetItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
NS_IMETHOD GetVisibleItemCount(PRUint32 &aCount);
NS_IMETHOD GetVisibleItemAt(const PRUint32 aPos, nsISupports *& aMenuItem);
NS_IMETHOD InsertItemAt(const PRUint32 aPos, nsISupports * aMenuItem);
NS_IMETHOD RemoveItem(const PRUint32 aPos);
NS_IMETHOD RemoveAll();
NS_IMETHOD GetNativeData(void** aData);
NS_IMETHOD SetNativeData(void* aData);
NS_IMETHOD GetMenuContent(nsIContent ** aMenuNode);
NS_IMETHOD SetEnabled(PRBool aIsEnabled);
NS_IMETHOD GetEnabled(PRBool* aIsEnabled);
NS_IMETHOD ChangeNativeEnabledStatusForMenuItem(nsIMenuItem* aMenuItem, PRBool aEnabled);
NS_IMETHOD GetMenuRefAndItemIndexForMenuItem(nsISupports* aMenuItem,
void** aMenuRef,
PRUint16* aMenuItemIndex);
NS_IMETHOD SetupIcon();
nsEventStatus MenuSelected(const nsMenuEvent & aMenuEvent);
void MenuDeselected(const nsMenuEvent & aMenuEvent);
void MenuConstruct(const nsMenuEvent & aMenuEvent, nsIWidget * aParentWindow, void * aMenuNode);
void MenuDestruct(const nsMenuEvent & aMenuEvent);
void SetRebuild(PRBool aMenuEvent);
// nsMenuX
nsresult Create(nsMenuObjectX* aParent, const nsAString &aLabel,
nsMenuBarX* aMenuBar, nsIContent* aNode);
PRUint32 GetItemCount();
nsMenuObjectX* GetItemAt(PRUint32 aPos);
nsresult GetVisibleItemCount(PRUint32 &aCount);
nsMenuObjectX* GetVisibleItemAt(PRUint32 aPos);
nsEventStatus MenuOpened(const nsMenuEvent& aMenuEvent);
void MenuClosed(const nsMenuEvent& aMenuEvent);
void SetRebuild(PRBool aMenuEvent);
NSMenuItem* NativeMenuItem();
protected:
// Determines how many menus are visible among the siblings that are before me.
// It doesn't matter if I am visible.
nsresult CountVisibleBefore(PRUint32* outVisibleBefore);
void MenuConstruct(nsIWidget* aParentWindow, void* aMenuNode);
nsresult RemoveAll();
nsresult SetEnabled(PRBool aIsEnabled);
nsresult GetEnabled(PRBool* aIsEnabled);
nsresult SetupIcon();
nsresult CountVisibleBefore(PRUint32* outVisibleBefore);
void GetMenuPopupContent(nsIContent** aResult);
PRBool OnOpen();
PRBool OnOpened();
PRBool OnClose();
PRBool OnClosed();
nsresult AddMenuItem(nsMenuItemX* aMenuItem);
nsresult AddMenu(nsMenuX* aMenu);
void LoadMenuItem(nsIContent* inMenuItemContent);
void LoadSubMenu(nsIContent* inMenuContent);
GeckoNSMenu* CreateMenuWithGeckoString(nsString& menuTitle);
// fetch the content node associated with the menupopup item
void GetMenuPopupContent(nsIContent** aResult);
// fire handlers for oncreate/ondestroy
PRBool OnDestroy();
PRBool OnCreate();
PRBool OnDestroyed();
PRBool OnCreated();
nsresult AddMenuItem(nsIMenuItem * aMenuItem);
nsresult AddMenu(nsIMenu * aMenu);
void LoadMenuItem(nsIContent* inMenuItemContent);
void LoadSubMenu(nsIContent* inMenuContent);
GeckoNSMenu* CreateMenuWithGeckoString(nsString& menuTitle);
protected:
nsString mLabel;
nsCOMArray<nsISupports> mMenuItemsArray;
PRUint32 mVisibleItemsCount; // caching number of visible items in mMenuItemsArray
nsISupports* mParent; // weak, my parent owns me
nsMenuBarX* mMenuBar; // weak ref, it will outlive us
nsCOMPtr<nsIContent> mMenuContent; // the |menu| tag, strong ref
nsRefPtr<nsMenuItemIconX> mIcon;
// Mac specific
PRInt16 mMacMenuID;
GeckoNSMenu* mMacMenu; // strong ref, we own it
MenuDelegate* mMenuDelegate; // strong ref, we keep this around to get events for us
NSMenuItem* mNativeMenuItem; // strong ref, we own
PRPackedBool mIsEnabled;
PRPackedBool mDestroyHandlerCalled;
PRPackedBool mNeedsRebuild;
PRPackedBool mConstructed;
PRPackedBool mVisible; // are we visible to the user?
PRPackedBool mXBLAttached;
nsTArray< nsAutoPtr<nsMenuObjectX> > mMenuObjectsArray;
nsString mLabel;
PRUint32 mVisibleItemsCount; // cache
nsMenuObjectX* mParent; // [weak]
nsMenuBarX* mMenuBar; // [weak]
nsRefPtr<nsMenuItemIconX> mIcon;
GeckoNSMenu* mMacMenu; // [strong]
MenuDelegate* mMenuDelegate; // [strong]
NSMenuItem* mNativeMenuItem; // [strong]
PRPackedBool mIsEnabled;
PRPackedBool mDestroyHandlerCalled;
PRPackedBool mNeedsRebuild;
PRPackedBool mConstructed;
PRPackedBool mVisible;
PRPackedBool mXBLAttached;
};
#endif // nsMenuX_h_

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -39,7 +39,7 @@
#include "nsISupports.idl"
interface nsIMenuBar;
interface nsMenuBarX;
interface nsCocoaWindow;
interface nsIWidget;
@ -56,9 +56,6 @@ interface nsPIWidgetCocoa : nsISupports
{
void SendSetZLevelEvent();
// Obtain the menubar for a window
nsIMenuBar GetMenuBar();
// Find the displayed child sheet (if aShown) or a child sheet that
// wants to be displayed (if !aShown)
nsCocoaWindow GetChildSheet(in boolean aShown);

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

@ -49,10 +49,6 @@
#include "nsAppShellSingleton.h"
#include "nsFilePicker.h"
#include "nsMenuBarX.h"
#include "nsMenuX.h"
#include "nsMenuItemX.h"
#include "nsClipboard.h"
#include "nsClipboardHelper.h"
#include "nsTransferable.h"
@ -74,9 +70,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsLookAndFeel)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuBarX)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuX)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMenuItemX)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
@ -89,6 +82,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsX, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSessionX, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceX)
#include "nsMenuBarX.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeMenuServiceX)
#include "nsBidiKeyboard.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
@ -125,18 +121,6 @@ static const nsModuleComponentInfo gComponents[] =
NS_LOOKANDFEEL_CID,
"@mozilla.org/widget/lookandfeel;1",
nsLookAndFeelConstructor },
{ "Menubar",
NS_MENUBAR_CID,
"@mozilla.org/widget/menubar/mac;1",
nsMenuBarXConstructor },
{ "Menu",
NS_MENU_CID,
"@mozilla.org/widget/menu/mac;1",
nsMenuXConstructor },
{ "MenuItem",
NS_MENUITEM_CID,
"@mozilla.org/widget/menuitem/mac;1",
nsMenuItemXConstructor },
{ "Sound",
NS_SOUND_CID,
"@mozilla.org/sound;1",
@ -189,6 +173,10 @@ static const nsModuleComponentInfo gComponents[] =
NS_IDLE_SERVICE_CID,
"@mozilla.org/widget/idleservice;1",
nsIdleServiceXConstructor },
{ "Native Menu Service",
NS_NATIVEMENUSERVICE_CID,
"@mozilla.org/widget/nativemenuservice;1",
nsNativeMenuServiceXConstructor },
};
NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(nsWidgetMacModule, gComponents,

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

@ -1373,7 +1373,7 @@ nsWindow::SetIcon(const nsAString& aIconSpec)
}
NS_IMETHODIMP
nsWindow::SetMenuBar(nsIMenuBar * aMenuBar)
nsWindow::SetMenuBar(void * aMenuBar)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

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

@ -141,7 +141,7 @@ public:
NS_IMETHOD SetTitle(const nsAString& aTitle);
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
NS_IMETHOD SetWindowClass(const nsAString& xulWinType);
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar);
NS_IMETHOD SetMenuBar(void * aMenuBar);
NS_IMETHOD ShowMenuBar(PRBool aShow);
NS_IMETHOD WidgetToScreen(const nsRect& aOldRect,
nsRect& aNewRect);

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

@ -61,7 +61,6 @@
#include "gfxOS2Surface.h"
#include "gfxContext.h"
class nsIMenuBar;
class imgIContainer;
//#define DEBUG_FOCUS
@ -178,7 +177,7 @@ class nsWindow : public nsBaseWidget,
NS_IMETHOD HideWindowChrome(PRBool aShouldHide);
NS_IMETHOD SetTitle( const nsAString& aTitle);
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_ERROR_FAILURE; }
NS_IMETHOD Invalidate( PRBool aIsSynchronous);
NS_IMETHOD Invalidate( const nsRect & aRect, PRBool aIsSynchronous);
@ -281,7 +280,6 @@ protected:
PRInt32 mPreferredHeight;
PRInt32 mPreferredWidth;
nsToolkit *mOS2Toolkit;
nsIMenuBar *mMenuBar;
PRInt32 mWindowState;
nsRefPtr<gfxOS2Surface> mThebesSurface;

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

@ -53,7 +53,6 @@
#include "nsRect.h"
#include "nsTransform2D.h"
#include "nsGfxCIID.h"
#include "nsIMenuBar.h"
#include "nsToolkit.h"
#include "nsIPrefBranch.h"
#include "nsIPrefService.h"

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

@ -61,7 +61,6 @@
class nsNativeDragTarget;
class nsIRollupListener;
class nsIMenuBar;
class nsIFile;
class imgIContainer;
@ -190,7 +189,7 @@ public:
NS_IMETHOD ScrollRect(nsRect &aRect, PRInt32 aDx, PRInt32 aDy);
NS_IMETHOD SetTitle(const nsAString& aTitle);
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
NS_IMETHOD SetMenuBar(nsIMenuBar * aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD SetMenuBar(void * aMenuBar) { return NS_ERROR_FAILURE; }
NS_IMETHOD ShowMenuBar(PRBool aShow) { return NS_ERROR_FAILURE; }
NS_IMETHOD WidgetToScreen(const nsRect& aOldRect, nsRect& aNewRect);
NS_IMETHOD ScreenToWidget(const nsRect& aOldRect, nsRect& aNewRect);

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

@ -136,6 +136,7 @@ public:
virtual void ConvertToDeviceCoordinates(nscoord &aX,nscoord &aY) {}
virtual void FreeNativeData(void * data, PRUint32 aDataType) {}
NS_IMETHOD BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
protected:

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

@ -48,5 +48,10 @@ _TEST_FILES = test_bug343416.xul \
test_keycodes.xul \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
_TEST_FILES += native_menus_window.xul \
test_native_menus.xul
endif
libs:: $(_TEST_FILES)
$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)

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

@ -0,0 +1,115 @@
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Findbar Test code
-
- The Initial Developer of the Original Code is
- Mozilla Corporation.
- Portions created by the Initial Developer are Copyright (C) 2006
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Josh Aas <josh@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL or the LGPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<window id="NativeMenuWindow"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="300"
height="300"
onload="onLoad();"
title="Native Menu Test">
<command id="cmd_FooItem1" oncommand="executedCommandID = 'cmd_FooItem1';"/>
<command id="cmd_FooItem2" oncommand="executedCommandID = 'cmd_FooItem2';"/>
<command id="cmd_BarItem1" oncommand="executedCommandID = 'cmd_BarItem1';"/>
<command id="cmd_BarItem2" oncommand="executedCommandID = 'cmd_BarItem2';"/>
<menubar id="nativemenubar">
<menu id="foo" label="Foo">
<menupopup>
<menuitem label="FooItem1" command="cmd_FooItem1"/>
<menuitem label="FooItem2" command="cmd_FooItem2"/>
<menuseparator/>
<menu label="Bar">
<menupopup>
<menuitem label="BarItem1" command="cmd_BarItem1"/>
<menuitem label="BarItem2" command="cmd_BarItem2"/>
</menupopup>
</menu>
</menupopup>
</menu>
</menubar>
<script type="application/javascript"><![CDATA[
function ok(condition, message) {
window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
}
function onTestsFinished() {
window.close();
window.opener.wrappedJSObject.SimpleTest.finish();
}
var executedCommandID = "";
function testItem(location, targetID) {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var correctCommandHandler = false;
try {
utils.activateNativeMenuItemAt(location);
correctCommandHandler = executedCommandID == targetID;
}
catch (e) {
dump(e + "\n");
}
finally {
ok(correctCommandHandler, 'Command handler not run correctly');
executedCommandID = "";
}
}
function onLoad() {
var _delayedOnLoad = function() {
testItem("0|0", "cmd_FooItem1");
testItem("0|1", "cmd_FooItem2");
testItem("0|3|0", "cmd_BarItem1");
testItem("0|3|1", "cmd_BarItem2");
onTestsFinished()
}
setTimeout(_delayedOnLoad, 1000);
}
]]></script>
</window>

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

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Native menu system tests"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<title>Native menu system tests</title>
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
window.open("native_menus_window.xul", "NativeMenuWindow",
"chrome,width=600,height=600");
]]>
</script>
</window>

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

@ -109,8 +109,8 @@
#include "nsIMarkupDocumentViewer.h"
#include "nsIFocusEventSuppressor.h"
#if defined(XP_MACOSX)
#include "nsIMenuBar.h"
#ifdef XP_MACOSX
#include "nsINativeMenuService.h"
#define USE_NATIVE_MENUS
#endif
@ -122,9 +122,6 @@ static PRUint32 gWebShellWindowCount = 0;
/* Define Class IDs */
static NS_DEFINE_CID(kWindowCID, NS_WINDOW_CID);
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kMenuBarCID, NS_MENUBAR_CID);
#define SIZE_PERSISTENCE_TIMEOUT 500 // msec
nsWebShellWindow::nsWebShellWindow() : nsXULWindow()
@ -552,23 +549,17 @@ static void LoadNativeMenus(nsIDOMDocument *aDOMDoc, nsIWidget *aParentWindow)
aDOMDoc->GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"),
NS_LITERAL_STRING("menubar"),
getter_AddRefs(menubarElements));
nsCOMPtr<nsIDOMNode> menubarNode;
if (menubarElements)
menubarElements->Item(0, getter_AddRefs(menubarNode));
if (!menubarNode)
return;
nsCOMPtr<nsIMenuBar> pnsMenuBar = do_CreateInstance(kMenuBarCID);
if (!pnsMenuBar)
return;
pnsMenuBar->Create(aParentWindow);
// fake event
nsMenuEvent fake(PR_TRUE, 0, nsnull);
pnsMenuBar->MenuConstruct(fake, aParentWindow, menubarNode);
nsCOMPtr<nsINativeMenuService> nms = do_GetService("@mozilla.org/widget/nativemenuservice;1");
nsCOMPtr<nsIContent> menubarContent(do_QueryInterface(menubarNode));
if (nms && menubarContent)
nms->CreateNativeMenuBar(aParentWindow, menubarContent);
}
#endif