gecko-dev/xpfe/appshell/src/nsWebShellWindow.cpp

2824 lines
86 KiB
C++
Raw Normal View History

1998-12-03 01:35:53 +00:00
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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/NPL/
*
* 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 Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsWebShellWindow.h"
1999-05-16 10:02:19 +00:00
#include "nsLayoutCID.h"
#include "nsIDocumentLoader.h"
1999-05-16 10:02:19 +00:00
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
1998-12-03 01:35:53 +00:00
#include "nsIURL.h"
#ifdef NECKO
#include "nsIIOService.h"
#include "nsIURL.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#endif // NECKO
#include "nsIPref.h"
1998-12-03 01:35:53 +00:00
1999-04-20 22:35:11 +00:00
#include "nsINameSpaceManager.h"
#include "nsEscape.h"
#include "nsVoidArray.h"
1999-04-20 22:35:11 +00:00
#include "nsIScriptGlobalObject.h"
#include "nsIDOMWindow.h"
1999-05-18 09:03:26 +00:00
#include "nsIDOMEventTarget.h"
#include "nsIDOMFocusListener.h"
1999-05-16 08:10:27 +00:00
#include "nsIXULParentDocument.h"
1999-05-18 09:03:26 +00:00
#include "nsIXULPopupListener.h"
#include "nsIXULChildDocument.h"
#include "nsIDOMXULElement.h"
1999-05-18 09:03:26 +00:00
#include "nsRDFCID.h"
1999-05-16 08:10:27 +00:00
1998-12-03 01:35:53 +00:00
#include "nsGUIEvent.h"
#include "nsWidgetsCID.h"
#include "nsIWidget.h"
#include "nsIAppShell.h"
#include "nsIXULWindowCallbacks.h"
1998-12-03 01:35:53 +00:00
#include "nsIAppShellService.h"
#include "nsAppShellCIDs.h"
#include "nsXULCommand.h"
1999-01-27 04:02:33 +00:00
#include "nsIDOMCharacterData.h"
#include "nsIDOMNodeList.h"
#include "nsIMenuBar.h"
#include "nsIMenu.h"
#include "nsIMenuItem.h"
#include "nsIMenuListener.h"
1999-05-14 22:28:00 +00:00
#include "nsIContextMenu.h"
1999-02-18 05:01:03 +00:00
// For JS Execution
#include "nsIScriptContextOwner.h"
#include "nsIEventQueueService.h"
#include "plevent.h"
#include "prmem.h"
#include "nsIDocumentViewer.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsIDocumentLoader.h"
#include "nsIObserverService.h"
#include "prprf.h"
//#include "nsIDOMHTMLInputElement.h"
//#include "nsIDOMHTMLImageElement.h"
#include "nsIContent.h" // for menus
// For calculating size
#include "nsIFrame.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
// HACK for M4, should be removed by M5
#ifdef XP_MAC
#include <Menus.h>
#endif
#include "nsIMenuItem.h"
#include "nsIDOMXULDocument.h"
// End hack
#include "nsIWindowMediator.h"
// This is to bring up a MsgCompose window when a mailto link is clicked.
// This is a temporary hack for M8 until NECKO lands when I can use their
// Protocol registry
#include "nsIDOMToolkitCore.h"
#include "nsAppCoresCIDs.h"
1998-12-03 01:35:53 +00:00
/* Define Class IDs */
static NS_DEFINE_IID(kWindowCID, NS_WINDOW_CID);
static NS_DEFINE_IID(kWebShellCID, NS_WEB_SHELL_CID);
static NS_DEFINE_IID(kAppShellServiceCID, NS_APPSHELL_SERVICE_CID);
static NS_DEFINE_IID(kAppShellCID, NS_APPSHELL_CID);
1998-12-03 01:35:53 +00:00
1999-05-14 22:28:00 +00:00
#include "nsWidgetsCID.h"
static NS_DEFINE_IID(kMenuBarCID, NS_MENUBAR_CID);
static NS_DEFINE_IID(kMenuCID, NS_MENU_CID);
static NS_DEFINE_IID(kMenuItemCID, NS_MENUITEM_CID);
1999-05-14 22:28:00 +00:00
static NS_DEFINE_IID(kContextMenuCID, NS_CONTEXTMENU_CID);
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_IID(kToolkitCoreCID, NS_TOOLKITCORE_CID);
static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
static NS_DEFINE_IID(kIDocumentLoaderFactoryIID, NS_IDOCUMENTLOADERFACTORY_IID);
static NS_DEFINE_CID(kLayoutDocumentLoaderFactoryCID, NS_LAYOUT_DOCUMENT_LOADER_FACTORY_CID);
#ifndef NECKO
#ifdef MOZ_MAIL_NEWS
static NS_DEFINE_CID(kMsgComposeServiceCID, NS_MSGCOMPOSESERVICE_CID);
#endif /* MOZ_MAIL_NEWS */
#endif /* NECKO */
1998-12-03 01:35:53 +00:00
/* Define Interface IDs */
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIWebShellWindowIID, NS_IWEBSHELL_WINDOW_IID);
static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID);
static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID);
static NS_DEFINE_IID(kIWebShellContainerIID, NS_IWEB_SHELL_CONTAINER_IID);
static NS_DEFINE_IID(kIBrowserWindowIID, NS_IBROWSER_WINDOW_IID);
static NS_DEFINE_IID(kIAppShellServiceIID, NS_IAPPSHELL_SERVICE_IID);
static NS_DEFINE_IID(kIAppShellIID, NS_IAPPSHELL_IID);
static NS_DEFINE_IID(kIDocumentLoaderObserverIID, NS_IDOCUMENT_LOADER_OBSERVER_IID);
static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID);
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
1999-01-27 04:02:33 +00:00
static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID);
//static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID);
//static NS_DEFINE_IID(kIDOMHTMLImageElementIID, NS_IDOMHTMLIMAGEELEMENT_IID);
1998-12-03 01:35:53 +00:00
1999-05-14 22:28:00 +00:00
static NS_DEFINE_IID(kIMenuIID, NS_IMENU_IID);
static NS_DEFINE_IID(kIMenuBarIID, NS_IMENUBAR_IID);
static NS_DEFINE_IID(kIMenuItemIID, NS_IMENUITEM_IID);
static NS_DEFINE_IID(kIContextMenuIID, NS_ICONTEXTMENU_IID);
static NS_DEFINE_IID(kIXULCommandIID, NS_IXULCOMMAND_IID);
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
1998-12-03 01:35:53 +00:00
static NS_DEFINE_IID(kIWindowMediatorIID,NS_IWINDOWMEDIATOR_IID);
1999-05-18 09:03:26 +00:00
static NS_DEFINE_IID(kIXULPopupListenerIID, NS_IXULPOPUPLISTENER_IID);
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
static NS_DEFINE_IID(kIUrlDispatcherIID, NS_IURLDISPATCHER_IID);
#ifdef DEBUG_rods
#define DEBUG_MENUSDEL 1
#endif
1999-02-03 16:48:55 +00:00
1998-12-03 01:35:53 +00:00
#include "nsIWebShell.h"
1999-01-27 15:15:21 +00:00
const char * kThrobberOnStr = "resource:/res/throbber/anims07.gif";
const char * kThrobberOffStr = "resource:/res/throbber/anims00.gif";
1999-06-26 21:48:29 +00:00
const char * kPrimaryContentTypeValue = "content-primary";
1998-12-03 01:35:53 +00:00
struct ThreadedWindowEvent {
PLEvent event;
nsWebShellWindow *window;
};
// The web shell info object is used to hold information about content areas that will
// subsequently be filled in when we receive a webshell added notification.
struct nsWebShellInfo {
nsString id; // The identifier of the iframe or frame node in the XUL tree.
1999-06-26 21:48:29 +00:00
PRBool primary; // whether it's considered a/the primary content
1999-04-20 22:35:11 +00:00
nsIWebShell* child; // The child web shell that will end up being used for the content area.
1999-06-26 21:48:29 +00:00
nsWebShellInfo(const nsString& anID, PRBool aPrimary, nsIWebShell* aChildShell)
{
id = anID;
1999-06-26 21:48:29 +00:00
primary = aPrimary;
1999-04-20 22:35:11 +00:00
child = aChildShell;
NS_IF_ADDREF(aChildShell);
}
~nsWebShellInfo()
{
1999-04-20 22:35:11 +00:00
NS_IF_RELEASE(child);
}
};
1998-12-03 01:35:53 +00:00
nsWebShellWindow::nsWebShellWindow()
{
NS_INIT_REFCNT();
1998-12-03 01:35:53 +00:00
mWebShell = nsnull;
mWindow = nsnull;
mCallbacks = nsnull;
mContinueModalLoop = PR_FALSE;
mChromeInitialized = PR_FALSE;
mLockedUntilChromeLoad = PR_FALSE;
mContentShells = nsnull;
mChromeMask = NS_CHROME_ALL_CHROME;
mIntrinsicallySized = PR_FALSE;
1998-12-03 01:35:53 +00:00
}
nsWebShellWindow::~nsWebShellWindow()
{
if (nsnull != mWebShell) {
mWebShell->Destroy();
NS_RELEASE(mWebShell);
}
NS_IF_RELEASE(mWindow);
NS_IF_RELEASE(mCallbacks);
// Delete any remaining content shells.
PRInt32 count;
if (mContentShells && ((count = mContentShells->Count()) > 0)) {
for (PRInt32 i = 0; i < count; i++)
{
nsWebShellInfo* webInfo = (nsWebShellInfo*)(mContentShells->ElementAt(i));
delete webInfo;
}
delete mContentShells;
}
1998-12-03 01:35:53 +00:00
}
NS_IMETHODIMP_(nsrefcnt) nsWebShellWindow::AddRef(void)
{
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
++mRefCnt;
return mRefCnt;
}
1998-12-03 01:35:53 +00:00
NS_IMETHODIMP_(nsrefcnt) nsWebShellWindow::Release(void)
{
NS_PRECONDITION(0 != mRefCnt, "dup release");
--mRefCnt;
if (mRefCnt == 0) {
NS_DELETEXPCOM(this);
return 0;
}
return mRefCnt;
}
nsresult
nsWebShellWindow::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
nsresult rv = NS_NOINTERFACE;
if (NULL == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if ( aIID.Equals(kIWebShellWindowIID) ) {
*aInstancePtr = (void*) ((nsIWebShellWindow*)this);
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIWebShellContainerIID)) {
*aInstancePtr = (void*)(nsIWebShellContainer*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIDocumentLoaderObserverIID)) {
*aInstancePtr = (void*) ((nsIDocumentLoaderObserver*)this);
NS_ADDREF_THIS();
return NS_OK;
}
1999-06-22 03:04:11 +00:00
if ( aIID.Equals(kIBrowserWindowIID) ) {
*aInstancePtr = (void*) (nsIBrowserWindow*) this;
NS_ADDREF_THIS();
return NS_OK;
}
if ( aIID.Equals(kIUrlDispatcherIID) ) {
*aInstancePtr = (void*) (nsIUrlDispatcher*) this;
NS_ADDREF_THIS();
return NS_OK;
}
1999-06-22 03:04:11 +00:00
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)(nsIWebShellContainer*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return rv;
}
1998-12-03 01:35:53 +00:00
nsresult nsWebShellWindow::Initialize(nsIWebShellWindow* aParent,
nsIAppShell* aShell, nsIURI* aUrl,
nsIStreamObserver* anObserver,
nsIXULWindowCallbacks *aCallbacks,
PRInt32 aInitialWidth, PRInt32 aInitialHeight,
nsWidgetInitData& widgetInitData)
1998-12-03 01:35:53 +00:00
{
nsresult rv;
nsIWidget *parentWidget;
1998-12-03 01:35:53 +00:00
// XXX: need to get the default window size from prefs...
// Doesn't come from prefs... will come from CSS/XUL/RDF
nsRect r(0, 0, aInitialWidth, aInitialHeight);
1998-12-03 01:35:53 +00:00
// Create top level window
rv = nsComponentManager::CreateInstance(kWindowCID, nsnull, kIWidgetIID,
1998-12-03 01:35:53 +00:00
(void**)&mWindow);
if (NS_OK != rv) {
return rv;
1998-12-03 01:35:53 +00:00
}
if (!aParent || NS_FAILED(aParent->GetWidget(parentWidget)))
parentWidget = nsnull;
1998-12-03 01:35:53 +00:00
mWindow->SetClientData(this);
mWindow->Create(parentWidget, // Parent nsIWidget
1998-12-03 01:35:53 +00:00
r, // Widget dimensions
nsWebShellWindow::HandleEvent, // Event handler function
nsnull, // Device context
aShell, // Application shell
nsnull, // nsIToolkit
&widgetInitData); // Widget initialization data
1998-12-03 01:35:53 +00:00
mWindow->GetClientBounds(r);
mWindow->SetBackgroundColor(NS_RGB(192,192,192));
// Create web shell
rv = nsComponentManager::CreateInstance(kWebShellCID, nsnull,
1998-12-03 01:35:53 +00:00
kIWebShellIID,
(void**)&mWebShell);
if (NS_OK != rv) {
return rv;
1998-12-03 01:35:53 +00:00
}
r.x = r.y = 0;
rv = mWebShell->Init(mWindow->GetNativeData(NS_NATIVE_WIDGET),
r.x, r.y, r.width, r.height,
nsScrollPreference_kNeverScroll,
1998-12-03 01:35:53 +00:00
PR_TRUE, // Allow Plugins
PR_TRUE);
mWebShell->SetContainer(this);
mWebShell->SetObserver((nsIStreamObserver*)anObserver);
mWebShell->SetDocLoaderObserver(this);
// The outermost web shell is always considered to be chrome.
mWebShell->SetWebShellType(nsWebShellChrome);
/*
* XXX: How should preferences be supplied to the nsWebShellWindow?
* Should there be the notion of a global preferences service?
* Or should there be many preferences components based on
* the user profile...
*/
// Initialize the webshell with the preferences service
nsIPref *prefs;
rv = nsServiceManager::GetService(kPrefCID,
nsIPref::GetIID(),
(nsISupports **)&prefs);
if (NS_SUCCEEDED(rv)) {
// XXX Enforce the STANDARD compatibility mode? Nav Quirks causes
// the chrome to malfunction. Having this be a general pref applied
// everywhere seems bogus to me. We certainly don't want it on for
// the chrome.
prefs->SetIntPref("nglayout.compatibility.mode", eCompatibility_Standard);
prefs->SavePrefFile();
// Set the prefs in the outermost webshell.
mWebShell->SetPrefs(prefs);
nsServiceManager::ReleaseService(kPrefCID, prefs);
}
1998-12-03 01:35:53 +00:00
NS_IF_RELEASE(mCallbacks);
mCallbacks = aCallbacks;
NS_IF_ADDREF(mCallbacks);
if (nsnull != aUrl) {
#ifdef NECKO
char *tmpStr = NULL;
#else
const char *tmpStr = NULL;
#endif
nsString urlString;
aUrl->GetSpec(&tmpStr);
urlString = tmpStr;
#ifdef NECKO
nsCRT::free(tmpStr);
#endif
1999-04-22 00:05:59 +00:00
mWebShell->LoadURL(urlString.GetUnicode());
}
1998-12-03 01:35:53 +00:00
return rv;
}
/*
* Close the window
*/
NS_METHOD
nsWebShellWindow::Close()
{
ExitModalLoop();
if (mWebShell) {
mWebShell->Destroy();
NS_RELEASE(mWebShell);
}
NS_IF_RELEASE(mWindow);
nsIAppShellService* appShell;
nsresult rv = nsServiceManager::GetService(kAppShellServiceCID,
kIAppShellServiceIID,
(nsISupports**)&appShell);
if (NS_FAILED(rv))
return rv;
rv = appShell->UnregisterTopLevelWindow(this);
nsServiceManager::ReleaseService(kAppShellServiceCID, appShell);
1999-05-08 23:07:10 +00:00
return rv;
}
1998-12-03 01:35:53 +00:00
/*
* Event handler function...
*
* This function is called to process events for the nsIWidget of the
* nsWebShellWindow...
*/
nsEventStatus PR_CALLBACK
nsWebShellWindow::HandleEvent(nsGUIEvent *aEvent)
{
nsEventStatus result = nsEventStatus_eIgnore;
nsIWebShell* webShell = nsnull;
// Get the WebShell instance...
if (nsnull != aEvent->widget) {
void* data;
aEvent->widget->GetClientData(data);
if (nsnull != data) {
webShell = ((nsWebShellWindow*)data)->mWebShell;
}
}
if (nsnull != webShell) {
switch(aEvent->message) {
/*
* For size events, the WebShell must be resized to fill the entire
* client area of the window...
*/
case NS_SIZE: {
nsSizeEvent* sizeEvent = (nsSizeEvent*)aEvent;
webShell->SetBounds(0, 0, sizeEvent->windowSize->width, sizeEvent->windowSize->height);
result = nsEventStatus_eConsumeNoDefault;
break;
}
/*
* Notify the ApplicationShellService that the window is being closed...
*/
case NS_DESTROY: {
void* data;
aEvent->widget->GetClientData(data);
if (data)
((nsWebShellWindow *)data)->Close();
1998-12-03 01:35:53 +00:00
break;
}
1999-05-29 19:36:55 +00:00
case NS_GOTFOCUS: {
void* data;
aEvent->widget->GetClientData(data);
if (data) {
nsCOMPtr<nsIWebShell> contentShell;
((nsWebShellWindow *)data)->GetContentWebShell(getter_AddRefs(contentShell));
if (contentShell) {
nsCOMPtr<nsIDOMWindow> domWindow;
if (NS_SUCCEEDED(((nsWebShellWindow *)data)->
ConvertWebShellToDOMWindow(contentShell, getter_AddRefs(domWindow)))) {
domWindow->Focus();
}
}
}
}
1999-05-29 19:36:55 +00:00
default:
break;
1998-12-03 01:35:53 +00:00
}
}
return nsEventStatus_eIgnore;
}
NS_IMETHODIMP
nsWebShellWindow::WillLoadURL(nsIWebShell* aShell, const PRUnichar* aURL,
nsLoadType aReason)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::BeginLoadURL(nsIWebShell* aShell, const PRUnichar* aURL)
{
// If loading a new root .xul document, then redo chrome.
if (aShell == mWebShell) {
mChromeInitialized = PR_FALSE;
}
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::ProgressLoadURL(nsIWebShell* aShell, const PRUnichar* aURL,
PRInt32 aProgress, PRInt32 aProgressMax)
{
1999-01-27 04:02:33 +00:00
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::EndLoadURL(nsIWebShell* aWebShell, const PRUnichar* aURL,
1999-01-27 04:02:33 +00:00
PRInt32 aStatus)
{
return NS_OK;
}
//----------------------------------------
nsCOMPtr<nsIDOMNode> nsWebShellWindow::FindNamedParentFromDoc(nsIDOMDocument * aDomDoc, const nsString &aName)
{
nsCOMPtr<nsIDOMNode> node; // result.
nsCOMPtr<nsIDOMElement> element;
aDomDoc->GetDocumentElement(getter_AddRefs(element));
if (!element)
return node;
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(element));
if (!parent)
return node;
parent->GetFirstChild(getter_AddRefs(node));
while (node) {
nsString name;
node->GetNodeName(name);
#ifdef DEBUG_rods
printf("Looking for [%s] [%s]\n", aName.ToNewCString(), name.ToNewCString()); // this leaks
#endif
if (name.Equals(aName))
return node;
nsCOMPtr<nsIDOMNode> oldNode(node);
oldNode->GetNextSibling(getter_AddRefs(node));
}
node = do_QueryInterface(nsnull);
return node;
}
//----------------------------------------
NS_IMETHODIMP nsWebShellWindow::CreateMenu(nsIMenuBar * aMenuBar,
nsIDOMNode * aMenuNode,
nsString & aMenuName)
{
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, kIMenuIID, (void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
1999-03-20 02:56:03 +00:00
nsISupports * supports = nsnull;
aMenuBar->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, aMenuName);
NS_RELEASE(supports);
// Set nsMenu Name
pnsMenu->SetLabel(aMenuName);
// Make nsMenu a child of nsMenuBar
aMenuBar->AddMenu(pnsMenu);
// Open the node so that the contents are visible.
nsCOMPtr<nsIDOMElement> menuElement = do_QueryInterface(aMenuNode);
if (menuElement)
menuElement->SetAttribute("open", "true");
// Begin menuitem inner loop
nsCOMPtr<nsIDOMNode> menuitemNode;
aMenuNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
nsString menuitemName;
menuitemElement->GetNodeName(menuitemNodeType);
if (menuitemNodeType.Equals("menuitem")) {
// LoadMenuItem
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode);
} else if (menuitemNodeType.Equals("separator")) {
pnsMenu->AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Load a submenu
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
}
}
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
// The parent owns us, so we can release
NS_RELEASE(pnsMenu);
}
return NS_OK;
}
//----------------------------------------
NS_IMETHODIMP nsWebShellWindow::LoadMenuItem(
nsIMenu * pParentMenu,
nsIDOMElement * menuitemElement,
nsIDOMNode * menuitemNode)
{
nsString menuitemName;
nsString menuitemCmd;
menuitemElement->GetAttribute(nsAutoString("name"), menuitemName);
menuitemElement->GetAttribute(nsAutoString("cmd"), menuitemCmd);
// Create nsMenuItem
nsIMenuItem * pnsMenuItem = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuItemCID, nsnull, kIMenuItemIID, (void**)&pnsMenuItem);
if (NS_OK == rv) {
// Create MenuDelegate - this is the intermediator inbetween
// the DOM node and the nsIMenuItem
// The nsWebShellWindow wacthes for Document changes and then notifies the
// the appropriate nsMenuDelegate object
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(menuitemNode));
if (!domElement) {
return NS_ERROR_FAILURE;
}
pnsMenuItem->Create(pParentMenu, menuitemName, 0);
// Set nsMenuItem Name
//pnsMenuItem->SetLabel(menuitemName);
// Set key shortcut and modifiers
nsAutoString keyAtom("key");
nsString keyValue;
domElement->GetAttribute(keyAtom, keyValue);
// Try to find the key node.
nsCOMPtr<nsIDocument> document;
nsCOMPtr<nsIContent> content = do_QueryInterface(domElement);
if (NS_FAILED(rv = content->GetDocument(*getter_AddRefs(document)))) {
NS_ERROR("Unable to retrieve the document.");
return rv;
}
// Turn the document into a XUL document so we can use getElementById
nsCOMPtr<nsIDOMXULDocument> xulDocument = do_QueryInterface(document);
if (xulDocument == nsnull) {
NS_ERROR("not XUL!");
return NS_ERROR_FAILURE;
}
nsIDOMElement * keyElement = nsnull;
xulDocument->GetElementById(keyValue, &keyElement);
if(keyElement){
PRUint8 modifiers = knsMenuItemNoModifier;
nsAutoString shiftAtom("shift");
nsAutoString altAtom("alt");
nsAutoString commandAtom("command");
nsString shiftValue;
nsString altValue;
nsString commandValue;
nsString keyChar = " ";
keyElement->GetAttribute(keyAtom, keyChar);
keyElement->GetAttribute(shiftAtom, shiftValue);
keyElement->GetAttribute(altAtom, altValue);
keyElement->GetAttribute(commandAtom, commandValue);
if(keyChar != " ")
pnsMenuItem->SetShortcutChar(keyChar);
if(shiftValue == "true")
1999-07-03 00:31:23 +00:00
modifiers |= knsMenuItemShiftModifier;
if(altValue == "true")
1999-07-03 00:31:23 +00:00
modifiers |= knsMenuItemAltModifier;
if(commandValue == "false")
1999-07-03 00:31:23 +00:00
modifiers |= knsMenuItemCommandModifier;
pnsMenuItem->SetModifiers(modifiers);
}
// Make nsMenuItem a child of nsMenu
1999-03-20 02:56:03 +00:00
nsISupports * supports = nsnull;
pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports);
NS_RELEASE(supports);
nsAutoString cmdAtom("onclick");
nsString cmdName;
domElement->GetAttribute(cmdAtom, cmdName);
nsXULCommand * menuDelegate = new nsXULCommand();
menuDelegate->SetCommand(cmdName);
menuDelegate->SetWebShell(mWebShell);
menuDelegate->SetDOMElement(domElement);
menuDelegate->SetMenuItem(pnsMenuItem);
nsIXULCommand * icmd;
if (NS_OK == menuDelegate->QueryInterface(kIXULCommandIID, (void**) &icmd)) {
nsCOMPtr<nsIMenuListener> listener(do_QueryInterface(menuDelegate));
if (listener)
{
pnsMenuItem->AddMenuListener(listener);
#ifdef DEBUG_MENUSDEL
printf("Adding menu listener to [%s]\n", menuitemName.ToNewCString());
#endif
}
#ifdef DEBUG_MENUSDEL
else
{
printf("*** NOT Adding menu listener to [%s]\n", menuitemName.ToNewCString());
}
#endif
1999-04-27 09:38:56 +00:00
NS_RELEASE(icmd);
}
// The parent owns us, so we can release
NS_RELEASE(pnsMenuItem);
}
return NS_OK;
}
//----------------------------------------
void nsWebShellWindow::LoadSubMenu(
nsIMenu * pParentMenu,
nsIDOMElement * menuElement,
nsIDOMNode * menuNode)
{
nsString menuName;
menuElement->GetAttribute(nsAutoString("name"), menuName);
//printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
// Create nsMenu
nsIMenu * pnsMenu = nsnull;
nsresult rv = nsComponentManager::CreateInstance(kMenuCID, nsnull, kIMenuIID, (void**)&pnsMenu);
if (NS_OK == rv) {
// Call Create
1999-03-20 02:56:03 +00:00
nsISupports * supports = nsnull;
pParentMenu->QueryInterface(kISupportsIID, (void**) &supports);
pnsMenu->Create(supports, menuName);
NS_RELEASE(supports); // Balance QI
1999-07-07 00:48:06 +00:00
// Open the node so that the contents are visible.
menuElement->SetAttribute("open", "true");
// Set nsMenu Name
pnsMenu->SetLabel(menuName);
// Make nsMenu a child of parent nsMenu
1999-03-20 02:56:03 +00:00
//pParentMenu->AddMenu(pnsMenu);
supports = nsnull;
pnsMenu->QueryInterface(kISupportsIID, (void**) &supports);
pParentMenu->AddItem(supports);
NS_RELEASE(supports);
// Begin menuitem inner loop
nsCOMPtr<nsIDOMNode> menuitemNode;
menuNode->GetFirstChild(getter_AddRefs(menuitemNode));
while (menuitemNode) {
nsCOMPtr<nsIDOMElement> menuitemElement(do_QueryInterface(menuitemNode));
if (menuitemElement) {
nsString menuitemNodeType;
menuitemElement->GetNodeName(menuitemNodeType);
#ifdef DEBUG_saari
printf("Type [%s] %d\n", menuitemNodeType.ToNewCString(), menuitemNodeType.Equals("separator"));
#endif
if (menuitemNodeType.Equals("menuitem")) {
// Load a menuitem
LoadMenuItem(pnsMenu, menuitemElement, menuitemNode);
} else if (menuitemNodeType.Equals("separator")) {
pnsMenu->AddSeparator();
} else if (menuitemNodeType.Equals("menu")) {
// Add a submenu
LoadSubMenu(pnsMenu, menuitemElement, menuitemNode);
}
}
nsCOMPtr<nsIDOMNode> oldmenuitemNode(menuitemNode);
oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode));
} // end menu item innner loop
// The parent owns us, so we can release
NS_RELEASE(pnsMenu);
}
}
1999-04-19 08:23:18 +00:00
//----------------------------------------
void nsWebShellWindow::DynamicLoadMenus(nsIDOMDocument * aDOMDoc, nsIWidget * aParentWindow)
{
nsRect oldRect;
mWindow->GetClientBounds(oldRect);
1999-04-19 08:23:18 +00:00
// locate the window element which holds toolbars and menus and commands
nsCOMPtr<nsIDOMElement> element;
aDOMDoc->GetDocumentElement(getter_AddRefs(element));
if (!element) {
return;
}
nsCOMPtr<nsIDOMNode> window(do_QueryInterface(element));
nsresult rv;
int endCount = 0;
nsCOMPtr<nsIDOMNode> menubarNode(FindNamedDOMNode(nsAutoString("menubar"), window, endCount, 1));
if (menubarNode) {
nsIMenuBar * pnsMenuBar = nsnull;
rv = nsComponentManager::CreateInstance(kMenuBarCID, nsnull, kIMenuBarIID, (void**)&pnsMenuBar);
if (NS_OK == rv) {
if (nsnull != pnsMenuBar) {
1999-04-19 08:23:18 +00:00
// set pnsMenuBar as a nsMenuListener on aParentWindow
nsCOMPtr<nsIMenuListener> menuListener;
pnsMenuBar->QueryInterface(kIMenuListenerIID, getter_AddRefs(menuListener));
//fake event
nsMenuEvent fake;
menuListener->MenuConstruct(fake, aParentWindow, menubarNode, mWebShell);
// Resize around the menu.
1999-05-29 19:36:55 +00:00
rv = NS_ERROR_FAILURE;
// do a resize
nsCOMPtr<nsIContentViewerContainer> contentViewerContainer;
contentViewerContainer = do_QueryInterface(mWebShell);
if (!contentViewerContainer) {
NS_ERROR("Webshell doesn't support the content viewer container interface");
return;
}
nsCOMPtr<nsIContentViewer> contentViewer;
if (NS_FAILED(rv = contentViewerContainer->GetContentViewer(getter_AddRefs(contentViewer)))) {
NS_ERROR("Unable to retrieve content viewer.");
return;
}
nsCOMPtr<nsIDocumentViewer> docViewer;
docViewer = do_QueryInterface(contentViewer);
if (!docViewer) {
NS_ERROR("Document viewer interface not supported by the content viewer.");
return;
}
nsCOMPtr<nsIPresContext> presContext;
if (NS_FAILED(rv = docViewer->GetPresContext(*getter_AddRefs(presContext)))) {
NS_ERROR("Unable to retrieve the doc viewer's presentation context.");
return;
}
nsCOMPtr<nsIPresShell> presShell;
if (NS_FAILED(rv = presContext->GetShell(getter_AddRefs(presShell)))) {
NS_ERROR("Unable to retrieve the shell from the presentation context.");
return;
}
nsRect rect;
if (NS_FAILED(rv = mWindow->GetClientBounds(rect))) {
NS_ERROR("Failed to get web shells bounds");
return;
}
// Resize the browser window by the difference.
PRInt32 heightDelta = oldRect.height - rect.height;
nsRect currentBounds;
GetWindowBounds(currentBounds);
SizeWindowTo(currentBounds.width, currentBounds.height + heightDelta);
// END REFLOW CODE
1999-04-19 08:23:18 +00:00
} // end if ( nsnull != pnsMenuBar )
}
} // end if (menuBar)
1999-07-07 00:48:06 +00:00
} // nsWebShellWindow::DynamicLoadMenus
1999-04-19 08:23:18 +00:00
//----------------------------------------
void nsWebShellWindow::LoadMenus(nsIDOMDocument * aDOMDoc, nsIWidget * aParentWindow)
{
// locate the window element which holds toolbars and menus and commands
nsCOMPtr<nsIDOMElement> element;
aDOMDoc->GetDocumentElement(getter_AddRefs(element));
if (!element) {
return;
}
nsCOMPtr<nsIDOMNode> window(do_QueryInterface(element));
nsresult rv;
int endCount = 0;
nsCOMPtr<nsIDOMNode> menubarNode(FindNamedDOMNode(nsAutoString("menubar"), window, endCount, 1));
if (menubarNode) {
nsIMenuBar * pnsMenuBar = nsnull;
rv = nsComponentManager::CreateInstance(kMenuBarCID, nsnull, kIMenuBarIID, (void**)&pnsMenuBar);
if (NS_OK == rv) {
if (nsnull != pnsMenuBar) {
pnsMenuBar->Create(aParentWindow);
// set pnsMenuBar as a nsMenuListener on aParentWindow
nsCOMPtr<nsIMenuListener> menuListener;
pnsMenuBar->QueryInterface(kIMenuListenerIID, getter_AddRefs(menuListener));
aParentWindow->AddMenuListener(menuListener);
nsCOMPtr<nsIDOMNode> menuNode;
menubarNode->GetFirstChild(getter_AddRefs(menuNode));
while (menuNode) {
nsCOMPtr<nsIDOMElement> menuElement(do_QueryInterface(menuNode));
if (menuElement) {
nsString menuNodeType;
nsString menuName;
menuElement->GetNodeName(menuNodeType);
if (menuNodeType.Equals("menu")) {
menuElement->GetAttribute(nsAutoString("name"), menuName);
#ifdef DEBUG_rods
printf("Creating Menu [%s] \n", menuName.ToNewCString()); // this leaks
#endif
CreateMenu(pnsMenuBar, menuNode, menuName);
}
}
nsCOMPtr<nsIDOMNode> oldmenuNode(menuNode);
oldmenuNode->GetNextSibling(getter_AddRefs(menuNode));
} // end while (nsnull != menuNode)
// Give the aParentWindow this nsMenuBar to own.
aParentWindow->SetMenuBar(pnsMenuBar);
// HACK: force a paint for now
pnsMenuBar->Paint();
// HACK for M4, should be removed by M5
#ifdef XP_MAC
Handle tempMenuBar = ::GetMenuBar(); // Get a copy of the menu list
pnsMenuBar->SetNativeData((void*)tempMenuBar);
#endif
// The parent owns the menubar, so we can release it
NS_RELEASE(pnsMenuBar);
} // end if ( nsnull != pnsMenuBar )
}
} // end if (menuBar)
} // nsWebShellWindow::LoadMenus
1999-05-14 22:28:00 +00:00
//------------------------------------------------------------------------------
void nsWebShellWindow::DoContextMenu(
nsMenuEvent * aMenuEvent,
nsIDOMNode * aMenuNode,
nsIWidget * aParentWindow,
PRInt32 aX,
PRInt32 aY,
1999-06-09 10:13:46 +00:00
const nsString& aPopupAlignment,
const nsString& aAnchorAlignment)
1999-05-14 22:28:00 +00:00
{
if (aMenuNode) {
nsIContextMenu * pnsContextMenu;
nsresult rv = nsComponentManager::CreateInstance(kContextMenuCID, nsnull, kIContextMenuIID, (void**)&pnsContextMenu);
if (NS_SUCCEEDED(rv) && pnsContextMenu) {
nsISupports * supports;
aParentWindow->QueryInterface(kISupportsIID, (void**) &supports);
1999-06-09 10:13:46 +00:00
pnsContextMenu->Create(supports, aPopupAlignment, aAnchorAlignment);
1999-05-14 22:28:00 +00:00
NS_RELEASE(supports);
pnsContextMenu->SetLocation(aX,aY);
// Set webshell
1999-05-14 23:10:46 +00:00
pnsContextMenu->SetWebShell( mWebShell );
1999-05-14 22:28:00 +00:00
// Set DOM node
pnsContextMenu->SetDOMNode( aMenuNode );
// Construct and show menu
nsIMenuListener * listener;
pnsContextMenu->QueryInterface(kIMenuListenerIID, (void**) &listener);
// Dynamically construct and track the menu
listener->MenuSelected(*aMenuEvent);
// Destroy the menu
listener->MenuDeselected(*aMenuEvent);
// The parent owns the context menu, so we can release it
NS_RELEASE(listener);
1999-05-15 02:53:43 +00:00
NS_RELEASE(pnsContextMenu);
1999-05-14 22:28:00 +00:00
}
} // end if (aMenuNode)
}
//------------------------------------------------------------------------------
NS_IMETHODIMP
nsWebShellWindow::GetContentShellById(const nsString& aID, nsIWebShell** aChildShell)
{
// Set to null just to be certain
*aChildShell = nsnull;
// If we don't have a content array, we just don't care.
if (mContentShells == nsnull)
return NS_ERROR_FAILURE;
// Find out if the id in question is one that we have web shell info for.
PRInt32 count = mContentShells->Count();
for (PRInt32 i = 0; i < count; i++)
{
nsWebShellInfo* webInfo = (nsWebShellInfo*)(mContentShells->ElementAt(i));
if (webInfo->id == aID)
{
// We have a match!
*aChildShell = webInfo->child;
NS_ADDREF(*aChildShell);
return NS_OK;
}
}
return NS_ERROR_FAILURE;
}
1999-04-20 22:35:11 +00:00
1999-05-14 22:28:00 +00:00
//------------------------------------------------------------------------------
1999-04-20 22:35:11 +00:00
NS_IMETHODIMP
nsWebShellWindow::AddWebShellInfo(const nsString& aID,
1999-06-26 21:48:29 +00:00
PRBool aPrimary,
1999-04-20 22:35:11 +00:00
nsIWebShell* aChildShell)
{
1999-06-26 21:48:29 +00:00
nsWebShellInfo* webShellInfo = new nsWebShellInfo(aID, aPrimary,
aChildShell);
1999-04-20 22:35:11 +00:00
if (mContentShells == nsnull)
mContentShells = new nsVoidArray();
mContentShells->AppendElement((void*)webShellInfo);
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::ConvertWebShellToDOMWindow(nsIWebShell* aShell, nsIDOMWindow** aDOMWindow)
{
nsresult rv;
nsCOMPtr<nsIScriptContextOwner> newContextOwner;
nsCOMPtr<nsIScriptGlobalObject> newGlobalObject;
nsCOMPtr<nsIDOMWindow> newDOMWindow;
newContextOwner = do_QueryInterface(aShell);
if (newContextOwner)
{
if (NS_FAILED(rv = newContextOwner->GetScriptGlobalObject(getter_AddRefs(newGlobalObject)))) {
NS_ERROR("Unable to retrieve global object.");
return rv;
}
if (newGlobalObject) {
newDOMWindow = do_QueryInterface(newGlobalObject);
*aDOMWindow = newDOMWindow.get();
NS_ADDREF(*aDOMWindow);
}
else return NS_ERROR_FAILURE;
}
return NS_OK;
}
1999-05-14 22:41:09 +00:00
NS_IMETHODIMP
nsWebShellWindow::CreatePopup(nsIDOMElement* aElement, nsIDOMElement* aPopupContent,
PRInt32 aXPos, PRInt32 aYPos,
1999-06-09 08:36:06 +00:00
const nsString& aPopupType, const nsString& anAnchorAlignment,
const nsString& aPopupAlignment,
nsIDOMWindow* aWindow, nsIDOMWindow** outPopup)
1999-05-14 22:41:09 +00:00
{
1999-05-14 23:11:49 +00:00
nsresult rv = NS_OK;
// clear out result param up front. It's an error if a legal place to
// stick the result isn't provided.
if ( !outPopup ) {
NS_ERROR ( "Invalid param -- need to provide a place for result" );
return NS_ERROR_INVALID_ARG;
}
*outPopup = nsnull;
1999-05-14 23:11:49 +00:00
nsCOMPtr<nsIContentViewerContainer> contentViewerContainer;
contentViewerContainer = do_QueryInterface(mWebShell);
if (!contentViewerContainer) {
NS_ERROR("Webshell doesn't support the content viewer container interface");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIContentViewer> contentViewer;
if (NS_FAILED(rv = contentViewerContainer->GetContentViewer(getter_AddRefs(contentViewer)))) {
NS_ERROR("Unable to retrieve content viewer.");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocumentViewer> docViewer;
docViewer = do_QueryInterface(contentViewer);
if (!docViewer) {
NS_ERROR("Document viewer interface not supported by the content viewer.");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIPresContext> presContext;
if (NS_FAILED(rv = docViewer->GetPresContext(*getter_AddRefs(presContext)))) {
NS_ERROR("Unable to retrieve the doc viewer's presentation context.");
return NS_ERROR_FAILURE;
}
1999-06-09 09:02:35 +00:00
nsCOMPtr<nsIPresShell> presShell;
if (NS_FAILED(rv = presContext->GetShell(getter_AddRefs(presShell)))) {
NS_ERROR("Unable to retrieve the pres shell.");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (anAnchorAlignment != "none") {
// We need to compute our screen coordinates.
nsIFrame* primaryFrame;
presShell->GetPrimaryFrameFor(content, &primaryFrame);
if (primaryFrame) {
// Get the coordinates within the view.
nsRect rect;
nsIView * view;
nsPoint pnt;
primaryFrame->GetOffsetFromView(pnt, &view);
primaryFrame->GetRect(rect);
rect.x = pnt.x;
rect.y = pnt.y;
float t2p;
presContext->GetTwipsToPixels(&t2p);
rect.x = NSToCoordRound((float)(rect.x)*t2p);
rect.y = NSToCoordRound((float)(rect.y)*t2p);
rect.width = NSToCoordRound((float)(rect.width)*t2p);
rect.height = NSToCoordRound((float)(rect.height)*t2p);
if (anAnchorAlignment == "topleft") {
aXPos = rect.x + aXPos;
aYPos = rect.y + aYPos;
}
else if (anAnchorAlignment == "topright") {
aXPos = rect.x + rect.width + aXPos;
aYPos = rect.y + aYPos;
}
else if (anAnchorAlignment == "bottomleft") {
aXPos = rect.x + aXPos;
1999-06-09 09:05:53 +00:00
aYPos = rect.y + rect.height + aYPos;
1999-06-09 09:02:35 +00:00
}
else {
aXPos = rect.x + rect.width + aXPos;
aYPos = rect.y + rect.height + aYPos;
}
}
}
nsCOMPtr<nsIContent> popupContent = do_QueryInterface(aPopupContent);
if ( !popupContent )
return NS_OK; // It's ok. Really.
// Fire the CONSTRUCT DOM event to give JS/C++ a chance to build the popup
// dynamically. After we fire off the event, make sure we check the result
// for |nsEventStatus_eConsumeNoDefault| which translates into an event
// handler returning false. If that happens, abort creating the popup.
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_POPUP_CONSTRUCT;
rv = popupContent->HandleDOMEvent(*presContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
if ( NS_FAILED(rv) || status == nsEventStatus_eConsumeNoDefault )
return rv;
// Find out if we're a menu.
PRInt32 childCount;
popupContent->ChildCount(childCount);
if (childCount == 0)
return NS_OK;
1999-05-14 23:11:49 +00:00
nsCOMPtr<nsIContent> rootContent;
if (NS_FAILED(popupContent->ChildAt(0, *getter_AddRefs(rootContent))))
return NS_OK; // Doesn't matter. Don't report it.
nsString tagName;
nsCOMPtr<nsIDOMElement> rootElement = do_QueryInterface(rootContent);
if ( !rootElement || NS_FAILED(rootElement->GetTagName(tagName)))
return NS_OK; // It's ok. Really.
if (tagName == "menu") {
// XXX Need to distinguish between popup menus and context menus?
1999-06-09 10:13:46 +00:00
DoContextMenu(nsnull, rootElement, mWindow, aXPos, aYPos, aPopupAlignment, anAnchorAlignment);
// Fire the DESTRUCT DOM event to give JS/C++ a chance to destroy the popup contents
nsEventStatus status = nsEventStatus_eIgnore;
nsMouseEvent event;
event.eventStructType = NS_EVENT;
event.message = NS_POPUP_DESTRUCT;
rv = popupContent->HandleDOMEvent(*presContext, &event, nsnull, NS_EVENT_FLAG_INIT, status);
return rv;
1999-05-14 23:11:49 +00:00
}
if (tagName != "window")
return NS_OK; // I promise. It really is ok. Stop whining.
// Handle the arbitrary popup XUL case.
// (1) Create a top-level chromeless window. The size of the window can be specified
// on the window tag contained inside. Retrieve the webshell from the new nsWebShellWindow.
1999-05-16 07:52:02 +00:00
NS_WITH_SERVICE(nsIAppShellService, appShell, kAppShellServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIWebShellWindow> newWindow;
nsWebShellWindow* window = new nsWebShellWindow();
if (nsnull == window) {
return NS_ERROR_OUT_OF_MEMORY;
}
// temporarily disabling parentage because non-Windows platforms
// seem to be interpreting it in unexpected ways.
nsWidgetInitData widgetInitData;
widgetInitData.mBorderStyle = eBorderStyle_BorderlessTopLevel;
window->SetIntrinsicallySized(PR_TRUE);
rv = window->Initialize((nsIWebShellWindow *) nsnull, nsnull, nsnull,
nsnull, nsnull,
1, 1, widgetInitData);
if (NS_FAILED(rv))
return rv;
newWindow = window;
1999-05-16 07:52:02 +00:00
// Move the window to aXPos and aYPos
nsCOMPtr<nsIBrowserWindow> browserWindow = do_QueryInterface(newWindow);
browserWindow->MoveTo(aXPos, aYPos);
1999-05-18 10:29:48 +00:00
// (2) Get the webshell
1999-05-16 07:52:02 +00:00
nsCOMPtr<nsIWebShell> newShell;
newWindow->GetWebShell(*getter_AddRefs(newShell));
1999-05-16 07:52:02 +00:00
nsCOMPtr<nsIDOMWindow> domWindow;
if (NS_FAILED(rv = ConvertWebShellToDOMWindow(newShell, getter_AddRefs(domWindow)))) {
NS_ERROR("Unable to retrieve the DOM window from the new web shell.");
return rv;
}
1999-05-18 10:29:48 +00:00
// (3) We need to create a new document that clones the original document's popup
// content. This new document must use the different root and a different global script
// context (window object) but everything else about it is the same (namespaces, URLs,
// stylesheets).
1999-05-16 08:10:27 +00:00
nsCOMPtr<nsIDocument> document;
content->GetDocument(*getter_AddRefs(document));
if (document == nsnull)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIXULParentDocument> parentDocument = do_QueryInterface(document);
if (parentDocument == nsnull)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocument> popupDocument;
1999-05-18 09:03:26 +00:00
if (NS_FAILED(rv = parentDocument->CreatePopupDocument(rootContent, getter_AddRefs(popupDocument)))) {
1999-05-16 08:10:27 +00:00
NS_ERROR("Unable to create the child popup document.");
return rv;
}
// The tricky part now is bypassing the normal load process and just putting a document into
// the webshell. This is particularly nasty, since webshells don't normally even know
// about their documents
// (4) Create a document viewer
1999-05-16 10:02:19 +00:00
nsCOMPtr<nsIContentViewer> documentViewer;
nsCOMPtr<nsIDocumentLoaderFactory> docFactory;
if (NS_FAILED(rv = nsComponentManager::CreateInstance(kLayoutDocumentLoaderFactoryCID, nsnull,
kIDocumentLoaderFactoryIID,
(void**)getter_AddRefs(docFactory)))) {
NS_ERROR("Unable to instantiate layout's doc loader factory.");
return rv;
}
1999-05-16 10:02:19 +00:00
nsCOMPtr<nsIContentViewerContainer> cvContainer = do_QueryInterface(newShell);
1999-05-18 09:03:26 +00:00
if (NS_FAILED(rv = docFactory->CreateInstanceForDocument(cvContainer,
popupDocument,
"view",
1999-05-18 09:03:26 +00:00
getter_AddRefs(documentViewer)))) {
NS_ERROR("I couldn't get a document viewer for the popup document.");
return rv;
}
// (5) Feed the webshell to the content viewer
documentViewer->SetContainer(cvContainer);
// (6) Tell the content viewer container to embed the content viewer.
// (This step causes everything to be set up for an initial flow.)
1999-05-18 09:03:26 +00:00
if (NS_FAILED(rv = cvContainer->Embed(documentViewer, "view", nsnull))) {
NS_ERROR("Unable to embed the viewer in the container.");
return rv;
}
// (7) Hook up a blur handler to the window that will cause it to close.
1999-05-18 09:03:26 +00:00
nsCOMPtr<nsIXULPopupListener> popupListener;
if (NS_FAILED(rv = nsComponentManager::CreateInstance(kXULPopupListenerCID,
nsnull,
kIXULPopupListenerIID,
(void**) getter_AddRefs(popupListener)))) {
NS_ERROR("Unable to create an instance of the popup listener object.");
return rv;
}
nsIContent* popupRoot = popupDocument->GetRootContent();
nsCOMPtr<nsIDOMElement> popupRootElement = do_QueryInterface(popupRoot);
if (NS_FAILED(rv = popupListener->Init(popupRootElement, eXULPopupType_blur))) {
NS_ERROR("Unable to initialize our blur listener.");
return rv;
}
NS_IF_RELEASE(popupRoot);
nsCOMPtr<nsIDOMFocusListener> blurListener = do_QueryInterface(popupListener);
nsCOMPtr<nsIDOMEventTarget> targetWindow = do_QueryInterface(domWindow);
targetWindow->AddEventListener("blur", blurListener, PR_FALSE);
1999-05-18 10:29:48 +00:00
// (8) Set up the opener property
domWindow->SetOpener(aWindow);
// (9) Show the window. Don't give the focus yet because we may not want to.
// For example, popup windows want focus, but tooltips do not.
1999-05-18 09:03:26 +00:00
newWindow->Show(PR_TRUE);
1999-05-18 10:29:48 +00:00
// (10) Do some layout.
1999-05-18 09:03:26 +00:00
nsCOMPtr<nsIXULChildDocument> popupChild = do_QueryInterface(popupDocument);
popupChild->LayoutPopupDocument();
// return the popup.
*outPopup = domWindow;
NS_ADDREF(*outPopup);
1999-05-14 23:11:49 +00:00
return rv;
1999-05-14 22:41:09 +00:00
}
NS_IMETHODIMP
nsWebShellWindow::ContentShellAdded(nsIWebShell* aChildShell, nsIContent* frameNode)
{
// Find out the id of the frameNode in question
1999-06-26 21:48:29 +00:00
nsIAtom *idAtom = NS_NewAtom("id");
nsIAtom *typeAtom = NS_NewAtom("type");
PRBool isPrimary;
nsAutoString value;
1999-06-26 21:48:29 +00:00
// right now, any webshell with type "content" or "content-XXX" is
// considered a content webshell. but only "content-primary" is
// considered primary.
frameNode->GetAttribute(kNameSpaceID_None, typeAtom, value);
isPrimary = value.EqualsIgnoreCase(kPrimaryContentTypeValue) ? PR_TRUE : PR_FALSE;
frameNode->GetAttribute(kNameSpaceID_None, idAtom, value);
AddWebShellInfo(value, isPrimary, aChildShell);
// For some reason nsCOMPtr and do_queryInterface fail here
if (aChildShell) {
nsIUrlDispatcher * ud = nsnull;
QueryInterface(kIUrlDispatcherIID, (void **)&ud);
aChildShell->SetUrlDispatcher(ud);
NS_RELEASE(ud);
}
1999-06-26 21:48:29 +00:00
NS_RELEASE(typeAtom);
1999-04-20 22:35:11 +00:00
NS_RELEASE(idAtom);
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::NewWebShell(PRUint32 aChromeMask, PRBool aVisible,
nsIWebShell *&aNewWebShell)
{
nsresult rv;
NS_WITH_SERVICE(nsIAppShellService, appShell, kAppShellServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIWebShellWindow> newWindow;
PRBool openAsDialog = ((aChromeMask & NS_CHROME_OPEN_AS_DIALOG) != 0);
// XXX Check modal chrome flag to run a modal dialog!
if ((aChromeMask & NS_CHROME_OPEN_AS_CHROME) != 0) {
// Just do a nice normal create of a web shell and
// return it immediately.
if (openAsDialog)
rv = appShell->CreateDialogWindow(nsnull, nsnull, PR_FALSE, getter_AddRefs(newWindow),
nsnull, nsnull, NS_SIZETOCONTENT, NS_SIZETOCONTENT);
else rv = appShell->CreateTopLevelWindow(nsnull, nsnull, PR_FALSE, getter_AddRefs(newWindow),
nsnull, nsnull, NS_SIZETOCONTENT, NS_SIZETOCONTENT);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIBrowserWindow> browser(do_QueryInterface(newWindow));
if (browser)
browser->SetChrome(aChromeMask);
newWindow->GetWebShell(aNewWebShell); // GetWebShell does the addref.
}
return rv;
}
#ifdef XP_PC // XXX: Won't work on any other platforms yet. Sigh.
// We need to create a new top level window and then enter a nested
// loop. Eventually the new window will be told that it has loaded,
// at which time we know it is safe to spin out of the nested loop
// and allow the opening code to proceed.
// First push a nested event queue for event processing from netlib
// onto our UI thread queue stack.
NS_WITH_SERVICE(nsIEventQueueService, eQueueService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) {
NS_ERROR("Unable to obtain queue service.");
return rv;
}
eQueueService->PushThreadEventQueue();
nsCOMPtr<nsIURI> urlObj;
char * urlStr = "chrome://navigator/content/";
#ifndef NECKO
rv = NS_NewURL(getter_AddRefs(urlObj), urlStr);
#else
NS_WITH_SERVICE(nsIIOService, service, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsIURI *uri = nsnull;
rv = service->NewURI(urlStr, nsnull, &uri);
if (NS_FAILED(rv)) return rv;
rv = uri->QueryInterface(nsIURI::GetIID(), (void**)&urlObj);
NS_RELEASE(uri);
#endif // NECKO
if (NS_SUCCEEDED(rv)) {
if (openAsDialog)
rv = appShell->CreateDialogWindow(nsnull, urlObj, PR_FALSE, getter_AddRefs(newWindow),
nsnull, nsnull, 615, 480);
else rv = appShell->CreateTopLevelWindow(nsnull, urlObj, PR_FALSE, getter_AddRefs(newWindow),
nsnull, nsnull, 615, 480);
}
nsIAppShell *subshell;
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIBrowserWindow> browser(do_QueryInterface(newWindow));
if (browser)
browser->SetChrome(aChromeMask);
// Spin into the modal loop.
rv = nsComponentManager::CreateInstance(kAppShellCID, nsnull, kIAppShellIID, (void**)&subshell);
}
if (NS_SUCCEEDED(rv)) {
subshell->Create(0, nsnull);
subshell->Spinup(); // Spin up
// Specify that we want the window to remain locked until the chrome has loaded.
newWindow->LockUntilChromeLoad();
PRBool locked = PR_FALSE;
nsresult looprv = NS_OK;
newWindow->GetLockedState(locked);
while (NS_SUCCEEDED(looprv) && locked) {
void *data;
PRBool isRealEvent;
looprv = subshell->GetNativeEvent(isRealEvent, data);
subshell->DispatchNativeEvent(isRealEvent, data);
newWindow->GetLockedState(locked);
}
// Get rid of the nested UI thread queue used for netlib, and release the event queue service.
eQueueService->PopThreadEventQueue();
subshell->Spindown();
NS_RELEASE(subshell);
}
// We're out of the nested loop.
// During the layout of the new window, all content shells were located and placed
// into the new window's content shell array. Locate the "content area" content
// shell.
if (NS_SUCCEEDED(rv)) {
rv = newWindow->GetContentShellById("content", &aNewWebShell);
if (NS_FAILED(rv)) {
NS_ERROR("Unable to obtain a browser content shell.");
return rv;
}
}
#endif // XP_PC
return rv;
}
NS_IMETHODIMP nsWebShellWindow::FindWebShellWithName(const PRUnichar* aName,
nsIWebShell*& aResult)
{
nsresult rv = NS_OK;
nsString nameStr(aName);
1999-06-27 00:35:21 +00:00
// first, a special case
if (nameStr.EqualsIgnoreCase("_content"))
return GetContentWebShell(&aResult);
// Zero result (in case we fail).
aResult = nsnull;
// look for open windows with the given name
1999-06-27 00:35:21 +00:00
/* Note: this function arguably works as expected, but the end effect
is wrong. The webshell that catches the name given from a JavaScript
window.open call is the content, not the chrome, so a window whose
location is redirected will have its content replaced, not its chrome.
That may be the right choice; maybe not. Also, there's a visual problem
where the window position is reset.
So when two or three bad things get cleared up, this next bit will be
helpful. As it is, it's not too. */
NS_WITH_SERVICE(nsIWindowMediator, windowMediator, kWindowMediatorCID, &rv);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
if (NS_SUCCEEDED(windowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator)))) {
PRBool more;
// get the (main) webshell for each window in the enumerator
windowEnumerator->HasMoreElements(&more);
while (more) {
nsCOMPtr<nsISupports> protoWindow;
nsCOMPtr<nsIWebShell> webshell;
rv = windowEnumerator->GetNext(getter_AddRefs(protoWindow));
if (NS_SUCCEEDED(rv) && protoWindow) {
nsCOMPtr<nsIWebShellWindow> window(do_QueryInterface(protoWindow));
if (window) {
if (NS_SUCCEEDED(window->GetWebShell(*getter_AddRefs(webshell)))) {
// check the webshell, and then its children, for a name match
const PRUnichar *name;
if (NS_SUCCEEDED(webshell->GetName(&name)) && nameStr.Equals(name)) {
aResult = webshell;
NS_ADDREF(aResult);
break;
}
// Search for named frame within our root webshell. This will
// bypass the .xul document (and rightfully so). We need to be
// careful not to give that documents child frames names!
if (NS_SUCCEEDED(webshell->FindChildWithName(aName, aResult)) && aResult)
break;
}
}
}
windowEnumerator->HasMoreElements(&more);
}
}
} else
1999-06-27 00:35:21 +00:00
// should be redundant, but left in for now
if (mWebShell)
rv = mWebShell->FindChildWithName(aName, aResult);
return rv;
}
NS_IMETHODIMP
nsWebShellWindow::FocusAvailable(nsIWebShell* aFocusedWebShell, PRBool& aFocusTaken)
{
return NS_OK;
}
//----------------------------------------
// nsIWebShellWindow methods...
//----------------------------------------
NS_IMETHODIMP
nsWebShellWindow::Show(PRBool aShow)
{
mWebShell->Show(); // crimminy -- it doesn't take a parameter!
mWindow->Show(aShow);
1999-06-22 03:04:11 +00:00
nsresult rv;
NS_WITH_SERVICE(nsIWindowMediator, windowMediator, kWindowMediatorCID, &rv);
if ( NS_SUCCEEDED(rv) )
{
windowMediator->UpdateWindowTimeStamp( this );
}
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::ShowModal()
{
nsresult rv;
rv = ShowModalInternal();
return rv;
}
NS_IMETHODIMP
nsWebShellWindow::ShowModalInternal()
{
nsresult rv;
nsIAppShell *subshell;
// spin up a new application shell: event loops live there
rv = nsComponentManager::CreateInstance(kAppShellCID, nsnull, kIAppShellIID, (void**)&subshell);
if (NS_FAILED(rv))
return rv;
subshell->Create(0, nsnull);
subshell->Spinup();
nsIWidget *window = GetWidget();
window->SetModal();
NS_ADDREF(window);
mContinueModalLoop = PR_TRUE;
while (NS_SUCCEEDED(rv) && mContinueModalLoop == PR_TRUE) {
void *data;
PRBool isRealEvent,
processEvent;
rv = subshell->GetNativeEvent(isRealEvent, data);
if (NS_SUCCEEDED(rv)) {
subshell->EventIsForModalWindow(isRealEvent, data, window, &processEvent);
if (processEvent == PR_TRUE)
subshell->DispatchNativeEvent(isRealEvent, data);
}
}
subshell->Spindown();
NS_RELEASE(window);
NS_RELEASE(subshell);
return rv;
}
1999-06-26 21:48:29 +00:00
/* return the main, outermost webshell in this window */
NS_IMETHODIMP
nsWebShellWindow::GetWebShell(nsIWebShell *& aWebShell)
{
aWebShell = mWebShell;
NS_ADDREF(mWebShell);
return NS_OK;
}
1999-06-26 21:48:29 +00:00
/* return the webshell intended to hold (html) content. In a simple
browser window, that would be the main content area. If no such
webshell was found for any reason, the outermost webshell will be
returned. (Note that is the main chrome webshell, and probably
not what you wanted, but at least it's a webshell.)
Also note that if no content webshell was marked "primary,"
we return the chrome webshell, even if (non-primary) content webshells
do exist. Thas was done intentionally. The selection would be
nondeterministic, and it seems dangerous to set a precedent like that.
*/
NS_IMETHODIMP
nsWebShellWindow::GetContentWebShell(nsIWebShell **aResult)
{
nsresult rv;
nsIWebShell *content;
content = nsnull;
rv = NS_ERROR_FAILURE;
// first, try looking in the webshell list
// (note this list isn't dynamic: it's set up when the webshell is added,
// but not updated when its attributes are poked. could be a problem...)
if (mContentShells) {
PRInt32 count = mContentShells->Count();
for (PRInt32 ctr = 0; ctr < count; ctr++) {
nsWebShellInfo* webInfo = (nsWebShellInfo*)(mContentShells->ElementAt(ctr));
if (webInfo->primary) {
content = webInfo->child;
break;
}
}
}
if (!content)
// couldn't find it? then return our chrome webshell
content = mWebShell;
if (content) {
NS_ADDREF(content);
rv = NS_OK;
}
*aResult = content;
return rv;
}
NS_IMETHODIMP
nsWebShellWindow::GetWidget(nsIWidget *& aWidget)
{
aWidget = mWindow;
NS_ADDREF(mWindow);
return NS_OK;
}
void *
nsWebShellWindow::HandleModalDialogEvent(PLEvent *aEvent)
{
ThreadedWindowEvent *event = (ThreadedWindowEvent *) aEvent;
event->window->ShowModalInternal();
return 0;
}
void
nsWebShellWindow::DestroyModalDialogEvent(PLEvent *aEvent)
{
PR_Free(aEvent);
}
//----------------------------------------
// nsIDocumentLoaderObserver implementation
//----------------------------------------
NS_IMETHODIMP
nsWebShellWindow::OnStartDocumentLoad(nsIDocumentLoader* loader,
nsIURI* aURL, const char* aCommand)
{
return NS_OK;
}
NS_IMETHODIMP
#ifdef NECKO
nsWebShellWindow::OnEndDocumentLoad(nsIDocumentLoader* loader,
nsIChannel* channel, PRInt32 aStatus,
nsIDocumentLoaderObserver * aDocObserver)
#else
nsWebShellWindow::OnEndDocumentLoad(nsIDocumentLoader* loader,
nsIURI* aURL, PRInt32 aStatus,
nsIDocumentLoaderObserver * aDocObserver)
#endif
{
#ifdef DEBUG_MENUSDEL
printf("OnEndDocumentLoad\n");
#endif
/* We get notified every time a page/Frame is loaded. But we need to
* Load the menus, run the startup script etc.. only once. So, Use
* the mChrome Initialized member to check whether chrome should be
* initialized or not - Radha
*/
if (mChromeInitialized)
return NS_OK;
mChromeInitialized = PR_TRUE;
if (mLockedUntilChromeLoad) {
mLockedUntilChromeLoad = PR_FALSE;
}
// register as document listener
// this is needed for menus
nsCOMPtr<nsIContentViewer> cv;
mWebShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if (!docv)
return NS_OK;
nsCOMPtr<nsIDocument> doc;
docv->GetDocument(*getter_AddRefs(doc));
if (!doc)
return NS_OK;
doc->AddObserver(NS_STATIC_CAST(nsIDocumentObserver*, this));
}
ExecuteStartupCode();
///////////////////////////////
// Find the Menubar DOM and Load the menus, hooking them up to the loaded commands
///////////////////////////////
nsCOMPtr<nsIDOMDocument> menubarDOMDoc(GetNamedDOMDoc(nsAutoString("this"))); // XXX "this" is a small kludge for code reused
if (menubarDOMDoc)
1999-04-19 08:23:18 +00:00
{
#if defined XP_MAC || defined XP_BEOS
LoadMenus(menubarDOMDoc, mWindow);
1999-05-14 22:28:00 +00:00
// Context Menu test
nsCOMPtr<nsIDOMElement> element;
menubarDOMDoc->GetDocumentElement(getter_AddRefs(element));
nsCOMPtr<nsIDOMNode> window(do_QueryInterface(element));
1999-05-14 22:28:00 +00:00
int endCount = 0;
contextMenuTest = FindNamedDOMNode(nsAutoString("contextmenu"), window, endCount, 1);
1999-05-14 22:28:00 +00:00
// End Context Menu test
1999-04-23 23:06:52 +00:00
#else
DynamicLoadMenus(menubarDOMDoc, mWindow);
1999-04-19 08:23:18 +00:00
#endif
}
SetTitleFromXUL();
ShowAppropriateChrome();
LoadContentAreas();
// Always show the window at this point.
mWindow->Show(PR_TRUE);
mWebShell->Show();
return NS_OK;
}
NS_IMETHODIMP
#ifdef NECKO
nsWebShellWindow::OnStartURLLoad(nsIDocumentLoader* loader,
nsIChannel* channel,
nsIContentViewer* aViewer)
#else
nsWebShellWindow::OnStartURLLoad(nsIDocumentLoader* loader,
nsIURI* aURL,
const char* aContentType,
nsIContentViewer* aViewer)
#endif
{
return NS_OK;
}
NS_IMETHODIMP
#ifdef NECKO
nsWebShellWindow::OnProgressURLLoad(nsIDocumentLoader* loader,
nsIChannel* channel,
PRUint32 aProgress,
PRUint32 aProgressMax)
#else
nsWebShellWindow::OnProgressURLLoad(nsIDocumentLoader* loader,
nsIURI* aURL,
PRUint32 aProgress,
PRUint32 aProgressMax)
#endif
{
return NS_OK;
}
NS_IMETHODIMP
#ifdef NECKO
nsWebShellWindow::OnStatusURLLoad(nsIDocumentLoader* loader,
nsIChannel* channel, nsString& aMsg)
#else
nsWebShellWindow::OnStatusURLLoad(nsIDocumentLoader* loader,
nsIURI* aURL, nsString& aMsg)
#endif
{
return NS_OK;
}
NS_IMETHODIMP
#ifdef NECKO
nsWebShellWindow::OnEndURLLoad(nsIDocumentLoader* loader,
nsIChannel* channel, PRInt32 aStatus)
#else
nsWebShellWindow::OnEndURLLoad(nsIDocumentLoader* loader,
nsIURI* aURL, PRInt32 aStatus)
#endif
{
return NS_OK;
}
1999-04-08 04:21:15 +00:00
NS_IMETHODIMP
#ifdef NECKO
nsWebShellWindow::HandleUnknownContentType(nsIDocumentLoader* loader,
nsIChannel* channel,
const char *aContentType,
const char *aCommand )
#else
nsWebShellWindow::HandleUnknownContentType(nsIDocumentLoader* loader,
nsIURI* aURL,
1999-04-08 04:21:15 +00:00
const char *aContentType,
const char *aCommand )
#endif
1999-04-08 04:21:15 +00:00
{
return NS_OK;
}
//----------------------------------------
nsCOMPtr<nsIDOMNode> nsWebShellWindow::FindNamedDOMNode(const nsString &aName, nsIDOMNode * aParent, PRInt32 & aCount, PRInt32 aEndCount)
{
1999-07-04 02:43:58 +00:00
if(!aParent)
return nsnull;
nsCOMPtr<nsIDOMNode> node;
aParent->GetFirstChild(getter_AddRefs(node));
while (node) {
1999-01-27 04:02:33 +00:00
nsString name;
node->GetNodeName(name);
//printf("FindNamedDOMNode[%s]==[%s] %d == %d\n", aName.ToNewCString(), name.ToNewCString(), aCount+1, aEndCount); //this leaks
1999-01-27 04:02:33 +00:00
if (name.Equals(aName)) {
aCount++;
if (aCount == aEndCount)
1999-01-27 04:02:33 +00:00
return node;
}
PRBool hasChildren;
node->HasChildNodes(&hasChildren);
if (hasChildren) {
nsCOMPtr<nsIDOMNode> found(FindNamedDOMNode(aName, node, aCount, aEndCount));
if (found)
1999-01-27 04:02:33 +00:00
return found;
}
nsCOMPtr<nsIDOMNode> oldNode = node;
oldNode->GetNextSibling(getter_AddRefs(node));
1999-01-27 04:02:33 +00:00
}
node = do_QueryInterface(nsnull);
return node;
} // nsWebShellWindow::FindNamedDOMNode
1999-01-27 04:02:33 +00:00
//----------------------------------------
nsCOMPtr<nsIDOMNode> nsWebShellWindow::GetParentNodeFromDOMDoc(nsIDOMDocument * aDOMDoc)
1999-01-27 04:02:33 +00:00
{
nsCOMPtr<nsIDOMNode> node; // null
1999-01-27 04:02:33 +00:00
if (nsnull == aDOMDoc) {
return node;
1999-01-27 04:02:33 +00:00
}
nsCOMPtr<nsIDOMElement> element;
aDOMDoc->GetDocumentElement(getter_AddRefs(element));
if (element)
return nsCOMPtr<nsIDOMNode>(do_QueryInterface(element));
1999-01-27 04:02:33 +00:00
return node;
} // nsWebShellWindow::GetParentNodeFromDOMDoc
1999-01-27 04:02:33 +00:00
//----------------------------------------
nsCOMPtr<nsIDOMDocument> nsWebShellWindow::GetNamedDOMDoc(const nsString & aWebShellName)
1999-01-27 04:02:33 +00:00
{
nsCOMPtr<nsIDOMDocument> domDoc; // result == nsnull;
// first get the toolbar child WebShell
nsCOMPtr<nsIWebShell> childWebShell;
if (aWebShellName.Equals("this")) { // XXX small kludge for code reused
childWebShell = do_QueryInterface(mWebShell);
} else {
1999-04-22 00:05:59 +00:00
mWebShell->FindChildWithName(aWebShellName.GetUnicode(), *getter_AddRefs(childWebShell));
if (!childWebShell)
return domDoc;
}
nsCOMPtr<nsIContentViewer> cv;
childWebShell->GetContentViewer(getter_AddRefs(cv));
if (!cv)
return domDoc;
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if (!docv)
return domDoc;
nsCOMPtr<nsIDocument> doc;
docv->GetDocument(*getter_AddRefs(doc));
if (doc)
return nsCOMPtr<nsIDOMDocument>(do_QueryInterface(doc));
1999-01-27 04:02:33 +00:00
return domDoc;
} // nsWebShellWindow::GetNamedDOMDoc
1999-01-27 04:02:33 +00:00
//----------------------------------------
PRInt32 nsWebShellWindow::GetDocHeight(nsIDocument * aDoc)
{
nsIPresShell * presShell = aDoc->GetShellAt(0);
1999-03-29 23:57:18 +00:00
if (!presShell)
return 0;
nsCOMPtr<nsIPresContext> presContext;
presShell->GetPresContext(getter_AddRefs(presContext));
if (presContext) {
nsRect rect;
presContext->GetVisibleArea(rect);
nsIFrame * rootFrame;
nsSize size;
presShell->GetRootFrame(&rootFrame);
if (rootFrame) {
rootFrame->GetSize(size);
float t2p;
presContext->GetTwipsToPixels(&t2p);
printf("Doc size %d,%d\n", PRInt32((float)size.width*t2p),
PRInt32((float)size.height*t2p));
//return rect.height;
return PRInt32((float)rect.height*t2p);
//return PRInt32((float)size.height*presContext->GetTwipsToPixels());
}
}
1999-03-29 23:57:18 +00:00
NS_RELEASE(presShell);
return 0;
}
1999-01-27 04:02:33 +00:00
//----------------------------------------
#if 0
1999-01-27 04:02:33 +00:00
NS_IMETHODIMP nsWebShellWindow::OnConnectionsComplete()
{
#ifdef DEBUG_MENUSDEL
printf("OnConnectionsComplete\n");
#endif
// register as document listener
// this is needed for menus
nsCOMPtr<nsIContentViewer> cv;
mWebShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if (!docv)
return NS_OK;
nsCOMPtr<nsIDocument> doc;
docv->GetDocument(*getter_AddRefs(doc));
if (!doc)
return NS_OK;
doc->AddObserver(NS_STATIC_CAST(nsIDocumentObserver*, this));
}
1999-02-18 05:01:03 +00:00
ExecuteStartupCode();
1999-01-27 04:02:33 +00:00
1999-02-18 05:01:03 +00:00
///////////////////////////////
// Find the Menubar DOM and Load the menus, hooking them up to the loaded commands
///////////////////////////////
nsCOMPtr<nsIDOMDocument> menubarDOMDoc(GetNamedDOMDoc(nsAutoString("this"))); // XXX "this" is a small kludge for code reused
1999-04-19 08:23:18 +00:00
if (menubarDOMDoc) {
1999-04-23 23:06:52 +00:00
#ifdef XP_MAC
1999-02-18 05:01:03 +00:00
LoadMenus(menubarDOMDoc, mWindow);
1999-04-23 23:06:52 +00:00
#else
DynamicLoadMenus(menubarDOMDoc, mWindow);
1999-04-19 08:23:18 +00:00
#endif
}
1999-03-29 23:57:18 +00:00
SetTitleFromXUL();
#if 0
nsCOMPtr<nsIDOMDocument> toolbarDOMDoc(GetNamedDOMDoc(nsAutoString("browser.toolbar")));
nsCOMPtr<nsIDOMDocument> contentDOMDoc(GetNamedDOMDoc(nsAutoString("browser.webwindow")));
1999-03-29 23:57:18 +00:00
nsCOMPtr<nsIDocument> contentDoc(do_QueryInterface(contentDOMDoc));
nsCOMPtr<nsIDocument> statusDoc(do_QueryInterface(statusDOMDoc));
nsCOMPtr<nsIDocument> toolbarDoc(do_QueryInterface(toolbarDOMDoc));
nsIWebShell* statusWebShell = nsnull;
mWebShell->FindChildWithName(nsAutoString("browser.status"), statusWebShell);
PRInt32 actualStatusHeight = GetDocHeight(statusDoc);
PRInt32 actualToolbarHeight = GetDocHeight(toolbarDoc);
PRInt32 height = 0;
PRInt32 x,y,w,h;
PRInt32 contentHeight;
PRInt32 toolbarHeight;
PRInt32 statusHeight;
mWebShell->GetBounds(x, y, w, h);
toolbarWebShell->GetBounds(x, y, w, toolbarHeight);
contentWebShell->GetBounds(x, y, w, contentHeight);
statusWebShell->GetBounds(x, y, w, statusHeight);
//h = toolbarHeight + contentHeight + statusHeight;
contentHeight = h - actualStatusHeight - actualToolbarHeight;
toolbarWebShell->GetBounds(x, y, w, h);
toolbarWebShell->SetBounds(x, y, w, actualToolbarHeight);
contentWebShell->GetBounds(x, y, w, h);
contentWebShell->SetBounds(x, y, w, contentHeight);
statusWebShell->GetBounds(x, y, w, h);
statusWebShell->SetBounds(x, y, w, actualStatusHeight);
#endif
return NS_OK;
} // nsWebShellWindow::OnConnectionsComplete
#endif /* 0 */
/**
* Get nsIDOMNode corresponding to a given webshell
* @param aShell the given webshell
* @return the corresponding DOM element, null if for some reason there is none
*/
nsCOMPtr<nsIDOMNode>
nsWebShellWindow::GetDOMNodeFromWebShell(nsIWebShell *aShell)
{
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIContentViewer> cv;
aShell->GetContentViewer(getter_AddRefs(cv));
if (cv) {
nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
if (docv) {
nsCOMPtr<nsIDocument> doc;
docv->GetDocument(*getter_AddRefs(doc));
if (doc) {
nsCOMPtr<nsIDOMDocument> domdoc(do_QueryInterface(doc));
if (domdoc) {
nsCOMPtr<nsIDOMElement> element;
domdoc->GetDocumentElement(getter_AddRefs(element));
if (element)
node = do_QueryInterface(element);
}
}
}
}
return node;
}
1999-02-18 05:01:03 +00:00
void nsWebShellWindow::ExecuteJavaScriptString(nsString& aJavaScript)
{
1999-02-18 05:01:03 +00:00
if (aJavaScript.Length() == 0) {
return;
}
1999-02-18 05:01:03 +00:00
// Get nsIScriptContextOwner
nsCOMPtr<nsIScriptContextOwner> scriptContextOwner ( do_QueryInterface(mWebShell) );
1999-02-18 05:01:03 +00:00
if ( scriptContextOwner ) {
const char* url = "";
// Get nsIScriptContext
nsCOMPtr<nsIScriptContext> scriptContext;
nsresult status = scriptContextOwner->GetScriptContext(getter_AddRefs(scriptContext));
if (NS_OK == status) {
// Ask the script context to evalute the javascript string
PRBool isUndefined = PR_FALSE;
nsString rVal("xxx");
scriptContext->EvaluateString(aJavaScript, url, 0, rVal, &isUndefined);
#ifdef DEBUG_MENUSDEL
printf("EvaluateString - %d [%s]\n", isUndefined, rVal.ToNewCString());
#endif
1999-02-18 05:01:03 +00:00
}
}
}
/**
* Execute window onLoad handler
*/
1999-02-18 05:01:03 +00:00
void nsWebShellWindow::ExecuteStartupCode()
{
1999-02-18 05:01:03 +00:00
nsCOMPtr<nsIDOMNode> webshellNode = GetDOMNodeFromWebShell(mWebShell);
nsCOMPtr<nsIDOMElement> webshellElement;
1999-02-18 05:01:03 +00:00
if (webshellNode)
webshellElement = do_QueryInterface(webshellNode);
if (mCallbacks)
mCallbacks->ConstructBeforeJavaScript(mWebShell);
// Execute the string in the onLoad attribute of the webshellElement.
1999-02-18 05:01:03 +00:00
nsString startupCode;
1999-06-10 00:36:08 +00:00
// This is now triggered from elsewhere.
//if (webshellElement && NS_SUCCEEDED(webshellElement->GetAttribute("onload", startupCode)))
// ExecuteJavaScriptString(startupCode);
if (mCallbacks)
mCallbacks->ConstructAfterJavaScript(mWebShell);
}
1999-03-29 23:57:18 +00:00
void nsWebShellWindow::SetTitleFromXUL()
{
nsCOMPtr<nsIDOMNode> webshellNode = GetDOMNodeFromWebShell(mWebShell);
nsIWidget *windowWidget = GetWidget();
nsCOMPtr<nsIDOMElement> webshellElement;
nsString windowTitle;
if (webshellNode)
webshellElement = do_QueryInterface(webshellNode);
if (webshellElement && windowWidget &&
NS_SUCCEEDED(webshellElement->GetAttribute("title", windowTitle)))
1999-05-20 06:19:14 +00:00
SetTitle(windowTitle.GetUnicode());
1999-03-29 23:57:18 +00:00
} // SetTitleFromXUL
// show/hide contents according to the current chrome mask
void nsWebShellWindow::ShowAppropriateChrome()
{
nsCOMPtr<nsIDOMElement> rootElement;
nsCOMPtr<nsIDOMXULElement> xulRoot;
nsCOMPtr<nsIDOMDocument> chromeDoc;
nsCOMPtr<nsIDOMWindow> domWindow;
// get this window's document
if (NS_FAILED(ConvertWebShellToDOMWindow(mWebShell, getter_AddRefs(domWindow))))
return;
if (NS_FAILED(domWindow->GetDocument(getter_AddRefs(chromeDoc))) || !chromeDoc)
return;
if (NS_FAILED(chromeDoc->GetDocumentElement(getter_AddRefs(rootElement))) || !rootElement)
return;
// special treatment for the menubar
ShowMenuBar(mChromeMask & NS_CHROME_MENU_BAR_ON ? PR_TRUE : PR_FALSE);
// get a list of this document's elements with the chromeclass attribute specified
xulRoot = do_QueryInterface(rootElement);
if (xulRoot) { // todo (maybe) the longer, straight DOM (not RDF) version?
nsCOMPtr<nsIDOMNodeList> chromeNodes;
if (NS_SUCCEEDED(xulRoot->GetElementsByAttribute("chromeclass", "*",
getter_AddRefs(chromeNodes)))) {
PRUint32 nodeCtr, nodeCount;
chromeNodes->GetLength(&nodeCount);
for (nodeCtr = 0; nodeCtr < nodeCount; nodeCtr++) {
nsCOMPtr<nsIDOMNode> domNode;
nsCOMPtr<nsIDOMElement> domElement;
chromeNodes->Item(nodeCtr, getter_AddRefs(domNode));
domElement = do_QueryInterface(domNode);
if (domElement) {
nsAutoString chromeClass;
PRBool makeChange;
PRUint32 flag;
// show or hide the element according to its chromeclass and the chromemask
domElement->GetAttribute("chromeclass", chromeClass);
makeChange = PR_FALSE;
if (chromeClass == "toolbar") {
makeChange = PR_TRUE;
flag = mChromeMask & NS_CHROME_TOOL_BAR_ON;
1999-06-04 04:01:20 +00:00
} else if (chromeClass == "location") {
makeChange = PR_TRUE;
flag = mChromeMask & NS_CHROME_LOCATION_BAR_ON;
} else if (chromeClass == "directories") {
makeChange = PR_TRUE;
flag = mChromeMask & NS_CHROME_PERSONAL_TOOLBAR_ON;
} else if (chromeClass == "status") {
makeChange = PR_TRUE;
flag = mChromeMask & NS_CHROME_STATUS_BAR_ON;
}
if (makeChange)
if (flag)
domElement->RemoveAttribute("chromehidden");
else
domElement->SetAttribute("chromehidden", "T");
}
}
}
}
}
// if the main document URL specified URLs for any content areas, start them loading
void nsWebShellWindow::LoadContentAreas() {
nsAutoString searchSpec;
// fetch the chrome document URL
nsCOMPtr<nsIContentViewer> contentViewer;
mWebShell->GetContentViewer(getter_AddRefs(contentViewer));
if (contentViewer) {
nsCOMPtr<nsIDocumentViewer> docViewer = do_QueryInterface(contentViewer);
if (docViewer) {
nsCOMPtr<nsIDocument> doc;
docViewer->GetDocument(*getter_AddRefs(doc));
nsCOMPtr<nsIURI> mainURL = getter_AddRefs(doc->GetDocumentURL());
if (mainURL) {
#ifdef NECKO
char *search = nsnull;
nsCOMPtr<nsIURL> url = do_QueryInterface(mainURL);
if (url)
url->GetQuery(&search);
#else
const char *search;
mainURL->GetSearch(&search);
#endif
searchSpec = search;
#ifdef NECKO
nsCRT::free(search);
#endif
}
}
}
// content URLs are specified in the search part of the URL
// as <contentareaID>=<escapedURL>[;(repeat)]
if (searchSpec.Length() > 0) {
PRInt32 begPos,
eqPos,
endPos;
nsString contentAreaID,
contentURL;
char *urlChar;
nsIWebShell *contentShell;
nsresult rv;
for (endPos = 0; endPos < searchSpec.Length(); ) {
// extract contentAreaID and URL substrings
begPos = endPos;
eqPos = searchSpec.Find('=', begPos);
if (eqPos < 0)
break;
endPos = searchSpec.Find(';', eqPos);
if (endPos < 0)
endPos = searchSpec.Length();
searchSpec.Mid(contentAreaID, begPos, eqPos-begPos);
searchSpec.Mid(contentURL, eqPos+1, endPos-eqPos-1);
endPos++;
// see if we have a webshell with a matching contentAreaID
rv = GetContentShellById(contentAreaID, &contentShell);
if (NS_SUCCEEDED(rv)) {
urlChar = contentURL.ToNewCString();
if (urlChar) {
nsUnescape(urlChar);
contentURL = urlChar;
contentShell->LoadURL(contentURL.GetUnicode());
delete [] urlChar;
}
NS_RELEASE(contentShell);
}
}
}
}
//----------------------------------------------------------------
//-- nsIDocumentObserver
//----------------------------------------------------------------
NS_IMETHODIMP
nsWebShellWindow::BeginUpdate(nsIDocument *aDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::EndUpdate(nsIDocument *aDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::BeginLoad(nsIDocument *aDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::EndLoad(nsIDocument *aDocument)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::EndReflow(nsIDocument *aDocument, nsIPresShell* aShell)
{
return NS_OK;
}
///////////////////////////////////////////////////////////////
// nsIDocumentObserver
// this is needed for menu changes
///////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsWebShellWindow::ContentChanged(nsIDocument *aDocument,
nsIContent* aContent,
nsISupports* aSubContent)
{
return NS_OK;
}
1999-02-27 08:34:06 +00:00
NS_IMETHODIMP
1999-04-20 00:06:58 +00:00
nsWebShellWindow::ContentStatesChanged(nsIDocument *aDocument,
nsIContent* aContent1,
nsIContent* aContent2)
1999-02-27 08:34:06 +00:00
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::AttributeChanged(nsIDocument *aDocument,
nsIContent* aContent,
nsIAtom* aAttribute,
PRInt32 aHint)
{
//printf("AttributeChanged\n");
PRInt32 i;
for (i=0;i<mMenuDelegates.Count();i++) {
nsIXULCommand * cmd = (nsIXULCommand *)mMenuDelegates[i];
nsIDOMElement * node;
cmd->GetDOMElement(&node);
//nsCOMPtr<nsIContent> content(do_QueryInterface(node));
// Doing this for the must speed
nsIContent * content;
if (NS_OK == node->QueryInterface(kIContentIID, (void**) &content)) {
if (content == aContent) {
nsAutoString attr;
aAttribute->ToString(attr);
cmd->AttributeHasBeenSet(attr);
}
NS_RELEASE(content);
}
}
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::ContentAppended(nsIDocument *aDocument,
nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::ContentInserted(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::ContentReplaced(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInContainer)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::ContentRemoved(nsIDocument *aDocument,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::StyleSheetAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::StyleSheetRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::StyleSheetDisabledStateChanged(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
PRBool aDisabled)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::StyleRuleChanged(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule,
PRInt32 aHint)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::StyleRuleAdded(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::StyleRuleRemoved(nsIDocument *aDocument,
nsIStyleSheet* aStyleSheet,
nsIStyleRule* aStyleRule)
{
return NS_OK;
}
NS_IMETHODIMP
nsWebShellWindow::DocumentWillBeDestroyed(nsIDocument *aDocument)
{
return NS_OK;
}
/**************** nsIBrowserWindow interface ********************/
NS_IMETHODIMP nsWebShellWindow::Init(nsIAppShell* aAppShell,
nsIPref* aPrefs,
const nsRect& aBounds,
PRUint32 aChromeMask,
PRBool aAllowPlugins)
{
nsresult rv;
nsCOMPtr<nsIURI> urlObj;
char * urlStr = "chrome://navigator/content/";
#ifndef NECKO
rv = NS_NewURL(getter_AddRefs(urlObj), urlStr);
#else
NS_WITH_SERVICE(nsIIOService, service, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsIURI *uri = nsnull;
rv = service->NewURI(urlStr, nsnull, &uri);
if (NS_FAILED(rv)) return rv;
rv = uri->QueryInterface(nsIURI::GetIID(), (void**)&urlObj);
NS_RELEASE(uri);
#endif // NECKO
if (NS_FAILED(rv))
return rv;
// Note: null nsIStreamObserver means this window won't be able to answer FE_callback-type
// questions from netlib. Observers are generally appcores. We'll have to supply
// a generic browser appcore here someday.
nsWidgetInitData widgetInitData;
widgetInitData.mBorderStyle = eBorderStyle_window;
rv = Initialize(nsnull, aAppShell, urlObj,
nsnull, nsnull, aBounds.width, aBounds.height, widgetInitData);
mChromeMask = aChromeMask;
if (NS_SUCCEEDED(rv))
MoveTo(aBounds.x, aBounds.y);
return rv;
}
NS_IMETHODIMP nsWebShellWindow::MoveTo(PRInt32 aX, PRInt32 aY)
{
mWindow->Move(aX, aY);
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::SizeWindowTo(PRInt32 aWidth, PRInt32 aHeight)
{
// XXX We have to look at the delta between our content shell's
// size and the size passed in and then resize ourselves based on that
// delta.
mIntrinsicallySized = PR_FALSE; // We got changed. No more intrinsic sizing here.
mWindow->Resize(aWidth, aHeight, PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::SizeContentTo(PRInt32 aWidth, PRInt32 aHeight)
{
PRInt32 x,y,width,height;
mWebShell->GetBounds(x,y,width,height);
PRInt32 aWidthDelta = aWidth - width;
PRInt32 aHeightDelta = aHeight - height;
nsRect windowBounds;
mWindow->GetBounds(windowBounds);
mWindow->Resize(windowBounds.width + aWidthDelta,
windowBounds.height + aHeightDelta,
PR_TRUE);
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::GetContentBounds(nsRect& aResult)
{
// Should return the size of the content webshell.
nsCOMPtr<nsIWebShell> contentShell;
GetContentWebShell(getter_AddRefs(contentShell));
if (!contentShell) {
NS_ERROR("Attempt to retrieve the content bounds for a window with no content.");
return NS_ERROR_FAILURE;
}
PRInt32 x,y,width,height;
contentShell->GetBounds(x,y,width,height);
aResult.x = x;
aResult.y = y;
aResult.width = width;
aResult.height = height;
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::GetWindowBounds(nsRect& aResult)
{
mWindow->GetBounds(aResult);
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::SetChrome(PRUint32 aNewChromeMask)
{
mChromeMask = aNewChromeMask;
ShowAppropriateChrome();
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::GetChrome(PRUint32& aChromeMaskResult)
{
aChromeMaskResult = mChromeMask;
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::SetTitle(const PRUnichar* aTitle)
{
nsIWidget *windowWidget = GetWidget();
// Get window modifier
nsCOMPtr<nsIDOMNode> webshellNode = GetDOMNodeFromWebShell(mWebShell);
nsCOMPtr<nsIDOMElement> webshellElement;
nsString windowTitleModifier;
1999-06-22 03:04:11 +00:00
nsString windowSeparator;
if (webshellNode)
webshellElement = do_QueryInterface(webshellNode);
if (webshellElement )
{
1999-06-22 03:04:11 +00:00
webshellElement->GetAttribute("titlemodifier", windowTitleModifier );
webshellElement->GetAttribute("titleseperator", windowSeparator );
}
1999-06-22 03:04:11 +00:00
nsString title( aTitle );
if( title.Length() > 0 )
title += windowSeparator+windowTitleModifier;
else
title = windowTitleModifier;
if (windowWidget)
windowWidget->SetTitle(title);
// Tell the window mediator that a title has changed
#if 1
{
nsIWindowMediator* service;
if (NS_FAILED(nsServiceManager::GetService(kWindowMediatorCID, kIWindowMediatorIID, (nsISupports**) &service ) ) )
return NS_OK;
service->UpdateWindowTitle( this, title.GetUnicode() );
nsServiceManager::ReleaseService(kWindowMediatorCID, service);
}
#endif // Window Mediation
return NS_OK;
}
NS_IMETHODIMP nsWebShellWindow::GetTitle(const PRUnichar** aResult)
{
// no, we didn't store the title for you. why so nosy?
return NS_ERROR_FAILURE;
}
// This should rightfully be somebody's PROGID?
// Will switch when the "app shell browser component" arrives.
static const char *prefix = "component://netscape/appshell/component/browser/window";
nsresult
nsWebShellWindow::NotifyObservers( const nsString &aTopic, const nsString &someData ) {
nsresult rv = NS_OK;
// Get observer service.
nsIObserverService *svc = 0;
rv = nsServiceManager::GetService( NS_OBSERVERSERVICE_PROGID,
nsIObserverService::GetIID(),
(nsISupports**)&svc );
if ( NS_SUCCEEDED( rv ) && svc ) {
// Notify observers as instructed; the subject is "this" web shell window.
nsString topic = prefix;
topic += ";";
topic += aTopic;
rv = svc->Notify( (nsIWebShellWindow*)this, topic.GetUnicode(), someData.GetUnicode() );
// Release the service.
nsServiceManager::ReleaseService( NS_OBSERVERSERVICE_PROGID, svc );
} else {
}
return rv;
}
NS_IMETHODIMP nsWebShellWindow::SetStatus(const PRUnichar* aStatus)
{
nsresult rv = NS_OK;
// Store status text.
mStatus = aStatus;
// Broadcast status text change to interested parties.
rv = NotifyObservers( "status", aStatus );
return rv;
}
NS_IMETHODIMP nsWebShellWindow::GetStatus(const PRUnichar** aResult)
{
nsresult rv = NS_OK;
if ( aResult ) {
// Semantics are ill-defined: How to allocate? Who frees it?
*aResult = mStatus.ToNewUnicode();
} else {
rv = NS_ERROR_NULL_POINTER;
}
return rv;
}
NS_IMETHODIMP nsWebShellWindow::SetProgress(PRInt32 aProgress, PRInt32 aProgressMax)
{
nsresult rv = NS_OK;
// Encode progress report in topic (there is no GetProgress for observers
// to query it).
char topic[32];
PR_snprintf( topic,
sizeof topic,
"%ld %ld",
(long)aProgress,
(long)aProgressMax );
// Broadcast progress info to interested parties.
rv = NotifyObservers( "progress", topic );
return rv;
}
NS_IMETHODIMP
nsWebShellWindow::ShowMenuBar(PRBool aShow)
{
if (aShow)
mChromeMask |= NS_CHROME_MENU_BAR_ON;
else
mChromeMask &= ~NS_CHROME_MENU_BAR_ON;
return mWindow->ShowMenuBar(aShow);
}
NS_IMETHODIMP
nsWebShellWindow::IsMenuBarVisible(PRBool *aVisible)
{
return mWindow->IsMenuBarVisible(aVisible);
}
//nsIUrlDispatcher methods
NS_IMETHODIMP
nsWebShellWindow::HandleUrl(const PRUnichar * aCommand, const PRUnichar * aURLSpec, nsIPostData * aPostData)
{
/* Make the topic to observe. The topic will be of the format
* linkclick:<prototocol>. Note thet this is a totally made up thing.
* Things are going to change later
*/
nsString topic(aCommand);
topic += ":";
nsAutoString url(aURLSpec);
nsresult rv;
PRInt32 offset = url.Find(":");
if (offset <= 0)
return NS_ERROR_FAILURE;
PRInt32 offset2= url.Find("mailto:");
PRInt32 ret=0;
if (offset2 == 0) {
topic += "mailto";
/* I know about all that is going on regarding using window.open
* instead of showWindowWithArgs(). But, I really don't have another
* option in this case to invoke the messenger compose window.
* This piece of code will eventually go away when I start using the
* protocol registries in NECKO
*/
NS_WITH_SERVICE(nsIDOMToolkitCore, toolkitCore, kToolkitCoreCID, &rv)
if (NS_FAILED(rv))
return rv;
/* Messenger doesn't understand to:xyz@domain.com,subject="xyz" yet.
* So, just pass the type and mode info
*/
rv = toolkitCore->ShowWindowWithArgs("chrome://messengercompose/content",
nsnull,
"type=0,mode=0");
if (NS_FAILED(rv))
return rv;
}
else {
topic += "browser";
}
#if 0
printf("Topic to notify is %s %d\n", topic.ToNewCString(), ret);
NS_WITH_SERVICE(nsIObserverService, observer, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsISupports> subject(do_QueryInterface(this));
nsISupports * subject = nsnull;
QueryInterface(kISupportsIID, (void **)&subject);
if (!subject)
NS_ERROR_FAILURE;
rv = observer->Notify((nsISupports*)nsnull, topic.GetUnicode(), aURLSpec);
#endif /* 0 */
return NS_OK;
}
1999-07-06 18:53:41 +00:00
NS_IMETHODIMP
nsWebShellWindow::IsIntrinsicallySized(PRBool& aResult)
{
aResult = mIntrinsicallySized;
return NS_OK;
}