/* -*- 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" #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsIURL.h" #include "nsIPref.h" #include "nsINameSpaceManager.h" #include "nsVoidArray.h" #include "nsIScriptGlobalObject.h" #include "nsIDOMWindow.h" #include "nsGUIEvent.h" #include "nsWidgetsCID.h" #include "nsIWidget.h" #include "nsIAppShell.h" #include "nsIXULWindowCallbacks.h" #include "nsIAppShellService.h" #include "nsIWidgetController.h" #include "nsAppShellCIDs.h" #include "nsXULCommand.h" #include "nsIDOMCharacterData.h" #include "nsIDOMNodeList.h" #include "nsIMenuBar.h" #include "nsIMenu.h" #include "nsIMenuItem.h" #include "nsIMenuListener.h" // For JS Execution #include "nsIScriptContextOwner.h" #include "nsXPComCIID.h" #include "nsIEventQueueService.h" #include "plevent.h" #include "prmem.h" // XXX: Only needed for the creation of the widget controller... #include "nsIDocumentViewer.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsIDOMNode.h" #include "nsIDOMElement.h" #include "nsIDocumentLoader.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 #endif /* 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); static NS_DEFINE_IID(kMenuBarCID, NS_MENUBAR_CID); static NS_DEFINE_IID(kMenuCID, NS_MENU_CID); static NS_DEFINE_IID(kMenuItemCID, NS_MENUITEM_CID); static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); /* 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(kIWidgetControllerIID, NS_IWIDGETCONTROLLER_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); static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID); //static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); //static NS_DEFINE_IID(kIDOMHTMLImageElementIID, NS_IDOMHTMLIMAGEELEMENT_IID); 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(kIXULCommandIID, NS_IXULCOMMAND_IID); static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID); #ifdef DEBUG_rods #define DEBUG_MENUSDEL 1 #endif #include "nsIWebShell.h" const char * kThrobberOnStr = "resource:/res/throbber/anims07.gif"; const char * kThrobberOffStr = "resource:/res/throbber/anims00.gif"; 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. nsString name; // The name to apply to the webshell once we create it. nsString url; // The URL to load in the webshell once we create it. nsIWebShell* opener; // The web shell that will be the opener of this new shell. nsIWebShell* child; // The child web shell that will end up being used for the content area. nsWebShellInfo(const nsString& anID, const nsString aName, const nsString& anURL, nsIWebShell* anOpenerShell, nsIWebShell* aChildShell) { id = anID; name = aName; url = anURL; opener = anOpenerShell; NS_IF_ADDREF(anOpenerShell); child = aChildShell; NS_IF_ADDREF(aChildShell); } ~nsWebShellInfo() { NS_IF_RELEASE(opener); NS_IF_RELEASE(child); } }; nsWebShellWindow::nsWebShellWindow() { NS_INIT_REFCNT(); mWebShell = nsnull; mWindow = nsnull; mController = nsnull; mCallbacks = nsnull; mContinueModalLoop = PR_FALSE; mChromeInitialized = PR_FALSE; mContentShells = nsnull; } nsWebShellWindow::~nsWebShellWindow() { if (nsnull != mWebShell) { mWebShell->Destroy(); NS_RELEASE(mWebShell); } NS_IF_RELEASE(mWindow); NS_IF_RELEASE(mController); 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; } } NS_IMPL_ADDREF(nsWebShellWindow); NS_IMPL_RELEASE(nsWebShellWindow); 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; } if ( aIID.Equals(kIBrowserWindowIID) ) { *aInstancePtr = (void*) (nsIBrowserWindow*) this; NS_ADDREF_THIS(); return NS_OK; } if (aIID.Equals(kISupportsIID)) { *aInstancePtr = (void*)(nsISupports*)(nsIWebShellContainer*)this; NS_ADDREF_THIS(); return NS_OK; } return rv; } nsresult nsWebShellWindow::Initialize(nsIWebShellWindow* aParent, nsIAppShell* aShell, nsIURL* aUrl, nsString& aControllerIID, nsIStreamObserver* anObserver, nsIXULWindowCallbacks *aCallbacks, PRInt32 aInitialWidth, PRInt32 aInitialHeight) { nsresult rv; nsString urlString; nsIWidget *parentWidget; const char *tmpStr = NULL; nsIID iid; char str[40]; // XXX: need to get the default window size from prefs... nsRect r(0, 0, aInitialWidth, aInitialHeight); nsWidgetInitData initData; //if (nsnull == aUrl) { // rv = NS_ERROR_NULL_POINTER; // goto done; //} if (nsnull != aUrl) { aUrl->GetSpec(&tmpStr); urlString = tmpStr; } // Create top level window rv = nsComponentManager::CreateInstance(kWindowCID, nsnull, kIWidgetIID, (void**)&mWindow); if (NS_OK != rv) { return rv; } initData.mBorderStyle = eBorderStyle_window; if (!aParent || NS_FAILED(aParent->GetWidget(parentWidget))) parentWidget = nsnull; mWindow->SetClientData(this); mWindow->Create(parentWidget, // Parent nsIWidget r, // Widget dimensions nsWebShellWindow::HandleEvent, // Event handler function nsnull, // Device context aShell, // Application shell nsnull, // nsIToolkit &initData); // Widget initialization data mWindow->GetClientBounds(r); mWindow->SetBackgroundColor(NS_RGB(192,192,192)); // Create web shell rv = nsComponentManager::CreateInstance(kWebShellCID, nsnull, kIWebShellIID, (void**)&mWebShell); if (NS_OK != rv) { return rv; } r.x = r.y = 0; rv = mWebShell->Init(mWindow->GetNativeData(NS_NATIVE_WIDGET), r.x, r.y, r.width, r.height, nsScrollPreference_kNeverScroll, 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)) { mWebShell->SetPrefs(prefs); nsServiceManager::ReleaseService(kPrefCID, prefs); } NS_IF_RELEASE(mCallbacks); mCallbacks = aCallbacks; NS_IF_ADDREF(mCallbacks); if (nsnull != aUrl) { mWebShell->LoadURL(urlString.GetUnicode()); } // Create the IWidgetController for the document... mController = nsnull; aControllerIID.ToCString(str, sizeof(str)); iid.Parse(str); //rv = nsComponentManager::CreateInstance(iid, nsnull, // kIWidgetControllerIID, // (void**)&mController); return rv; } /* * Close the window */ NS_METHOD nsWebShellWindow::Close() { ExitModalLoop(); NS_IF_RELEASE(mWindow); NS_IF_RELEASE(mWebShell); /* note: this next Release() seems like the right thing to do, but it doesn't appear exactly necessary, and we are afraid of possible repercussions unexplored at this time. ("this time" being a stability release crunch.) Revisit this later!? */ // Release(); nsIAppShellService* appShell; nsresult rv = nsServiceManager::GetService(kAppShellServiceCID, kIAppShellServiceIID, (nsISupports**)&appShell); if (NS_FAILED(rv)) return rv; rv = appShell->UnregisterTopLevelWindow(this); nsServiceManager::ReleaseService(kAppShellServiceCID, appShell); return rv; } /* * 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(); break; } } } 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) { return NS_OK; } NS_IMETHODIMP nsWebShellWindow::EndLoadURL(nsIWebShell* aWebShell, const PRUnichar* aURL, PRInt32 aStatus) { return NS_OK; } //---------------------------------------- nsCOMPtr nsWebShellWindow::FindNamedParentFromDoc(nsIDOMDocument * aDomDoc, const nsString &aName) { nsCOMPtr node; // result. nsCOMPtr element; aDomDoc->GetDocumentElement(getter_AddRefs(element)); if (!element) return node; nsCOMPtr 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 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 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); // Begin menuitem inner loop nsCOMPtr menuitemNode; aMenuNode->GetFirstChild(getter_AddRefs(menuitemNode)); while (menuitemNode) { nsCOMPtr 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 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) { pnsMenuItem->Create(pParentMenu, menuitemName, 0); // Set nsMenuItem Name //pnsMenuItem->SetLabel(menuitemName); // Make nsMenuItem a child of nsMenu //pParentMenu->AddMenuItem(pnsMenuItem); nsISupports * supports = nsnull; pnsMenuItem->QueryInterface(kISupportsIID, (void**) &supports); pParentMenu->AddItem(supports); NS_RELEASE(supports); // 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 domElement(do_QueryInterface(menuitemNode)); if (!domElement) { return NS_ERROR_FAILURE; } 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)) { mMenuDelegates.AppendElement(icmd); nsCOMPtr 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 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 nsISupports * supports = nsnull; pParentMenu->QueryInterface(kISupportsIID, (void**) &supports); pnsMenu->Create(supports, menuName); NS_RELEASE(supports); // Balance QI // Set nsMenu Name pnsMenu->SetLabel(menuName); // Make nsMenu a child of parent nsMenu //pParentMenu->AddMenu(pnsMenu); supports = nsnull; pnsMenu->QueryInterface(kISupportsIID, (void**) &supports); pParentMenu->AddItem(supports); NS_RELEASE(supports); // Begin menuitem inner loop nsCOMPtr menuitemNode; menuNode->GetFirstChild(getter_AddRefs(menuitemNode)); while (menuitemNode) { nsCOMPtr 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 oldmenuitemNode(menuitemNode); oldmenuitemNode->GetNextSibling(getter_AddRefs(menuitemNode)); } // end menu item innner loop // The parent owns us, so we can release NS_RELEASE(pnsMenu); } } //---------------------------------------- void nsWebShellWindow::DynamicLoadMenus(nsIDOMDocument * aDOMDoc, nsIWidget * aParentWindow) { // locate the window element which holds toolbars and menus and commands nsCOMPtr element; aDOMDoc->GetDocumentElement(getter_AddRefs(element)); if (!element) { return; } nsCOMPtr window(do_QueryInterface(element)); nsresult rv; int endCount = 0; nsCOMPtr 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) { // set pnsMenuBar as a nsMenuListener on aParentWindow nsCOMPtr menuListener; pnsMenuBar->QueryInterface(kIMenuListenerIID, getter_AddRefs(menuListener)); //fake event nsMenuEvent fake; menuListener->MenuConstruct(fake, aParentWindow, menubarNode, mWebShell); } // end if ( nsnull != pnsMenuBar ) } } // end if (menuBar) } // nsWebShellWindow::LoadMenus //---------------------------------------- void nsWebShellWindow::LoadMenus(nsIDOMDocument * aDOMDoc, nsIWidget * aParentWindow) { // locate the window element which holds toolbars and menus and commands nsCOMPtr element; aDOMDoc->GetDocumentElement(getter_AddRefs(element)); if (!element) { return; } nsCOMPtr window(do_QueryInterface(element)); nsresult rv; int endCount = 0; nsCOMPtr 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 menuListener; pnsMenuBar->QueryInterface(kIMenuListenerIID, getter_AddRefs(menuListener)); aParentWindow->AddMenuListener(menuListener); nsCOMPtr menuNode; menubarNode->GetFirstChild(getter_AddRefs(menuNode)); while (menuNode) { nsCOMPtr 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 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 NS_IMETHODIMP nsWebShellWindow::AddWebShellInfo(const nsString& aID, const nsString& aName, const nsString& anURL, nsIWebShell* aOpenerShell, nsIWebShell* aChildShell) { nsWebShellInfo* webShellInfo = new nsWebShellInfo(aID, aName, anURL, aOpenerShell, aChildShell); if (mContentShells == nsnull) mContentShells = new nsVoidArray(); mContentShells->AppendElement((void*)webShellInfo); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::ConvertWebShellToDOMWindow(nsIWebShell* aShell, nsIDOMWindow** aDOMWindow) { nsresult rv; nsCOMPtr newContextOwner; nsCOMPtr newGlobalObject; nsCOMPtr 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; } NS_IMETHODIMP nsWebShellWindow::ChildShellAdded(nsIWebShell** aChildShell, nsIContent* frameNode) { // 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_OK; // Find out if the frameNode in question is one that we have web shell info for. nsIAtom* idAtom = NS_NewAtom("id"); nsIAtom* srcAtom = NS_NewAtom("src"); nsAutoString value; frameNode->GetAttribute(kNameSpaceID_None, idAtom, value); PRInt32 count = mContentShells->Count(); for (PRInt32 i = 0; i < count; i++) { nsWebShellInfo* webInfo = (nsWebShellInfo*)(mContentShells->ElementAt(i)); if (webInfo->id == value) { // We have a match! // Alter the frame node's source using the nsIContent method (to ensure that // the value isn't persistently stored). frameNode->SetAttribute(kNameSpaceID_None, srcAtom, webInfo->url, PR_FALSE); *aChildShell = webInfo->child; NS_ADDREF(*aChildShell); // Remove this object from our array. mContentShells->RemoveElementAt(i); delete webInfo; return NS_OK; } } NS_RELEASE(idAtom); NS_RELEASE(srcAtom); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::NewWebShell(PRUint32 aChromeMask, PRBool aVisible, nsIWebShell *&aNewWebShell) { // Don't return a web shell, since the shell that will hold our content // hasn't been instantiated yet. We'll have to wait and set up the linkage // at a later date. aNewWebShell = nsnull; return NS_OK; } NS_IMETHODIMP nsWebShellWindow::CanCreateNewWebShell(PRBool& aResult) { aResult = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsWebShellWindow::SetNewWebShellInfo(const nsString& aName, const nsString& anURL, nsIWebShell* aOpenerShell, PRUint32 chrome, nsIWebShell** anOuterResult, nsIWebShell** anInnerResult) { // Create a new browser window. That's what this method is here for. nsresult rv; nsString controllerCID; nsIAppShellService *appShell; nsCOMPtr urlObj; rv = NS_NewURL(getter_AddRefs(urlObj), "chrome://navigator/content/"); if (NS_FAILED(rv)) return rv; rv = nsServiceManager::GetService(kAppShellServiceCID, kIAppShellServiceIID, (nsISupports**) &appShell); if (NS_FAILED(rv)) return rv; // hardwired temporary hack. See nsAppRunner.cpp at main() controllerCID = "43147b80-8a39-11d2-9938-0080c7cb1081"; nsCOMPtr newWindow; appShell->CreateTopLevelWindow(nsnull, urlObj, controllerCID, *getter_AddRefs(newWindow), nsnull, nsnull, 615, 480); nsServiceManager::ReleaseService(kAppShellServiceCID, appShell); // Now return the new window's web shell. newWindow->GetWebShell(*anOuterResult); // Create a new dummy shell that we will eventually want to reuse (when we find the // right place for it). // Create web shell nsIWebShell* dummyShell; rv = nsComponentManager::CreateInstance(kWebShellCID, nsnull, kIWebShellIID, (void**)&dummyShell); if (rv != NS_OK) { return rv; } // Return this inner dummy shell. Set this shell's container to point to the outer shell. *anInnerResult = dummyShell; dummyShell->SetContainer(this); // Cache our webshell info. newWindow->AddWebShellInfo("content", aName, anURL, aOpenerShell, dummyShell); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::FindWebShellWithName(const PRUnichar* aName, nsIWebShell*& aResult) { nsresult rv = NS_OK; // Zero result (in case we fail). aResult = nsnull; // 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! // // This will need to be enhanced to search for (owned?) named // windows at some point. 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); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::ShowModal() { nsresult rv; #if 0 // a nice though unnecessary shortcut should we happen to already be in the right thread if (PR_CurrentThread() == mozilla_thread) rv = ShowModalInternal(); else { ThreadedWindowEvent *event = PR_NEW(ThreadedWindowEvent); if (!event) rv = NS_ERROR_OUT_OF_MEMORY; else { PL_InitEvent(&event->event, NULL, HandleModalDialogEvent, DestroyModalDialogEvent); event->window = this; nsIEventQueueService *eQueueService; PLEventQueue *eQueue; rv = nsServiceManager::GetService(kEventQueueServiceCID, kIEventQueueServiceIID, (nsISupports **)&eQueueService); if (NS_SUCCEEDED(rv)) { rv = eQueueService->GetThreadEventQueue(mozilla_thread, &eQueue); NS_RELEASE(eQueueService); // nsServiceManager::ReleaseService(kEventQueueServiceCID, eQueue); (?) PL_PostSynchronousEvent(eQueue, &event->event); } rv = NS_OK; } } #else rv = ShowModalInternal(); #endif 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; } NS_IMETHODIMP nsWebShellWindow::GetWebShell(nsIWebShell *& aWebShell) { aWebShell = mWebShell; NS_ADDREF(mWebShell); return NS_OK; } 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, nsIURL* aURL, const char* aCommand) { return NS_OK; } NS_IMETHODIMP nsWebShellWindow::OnEndDocumentLoad(nsIDocumentLoader* loader, nsIURL* aURL, PRInt32 aStatus) { #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; // register as document listener // this is needed for menus nsCOMPtr cv; mWebShell->GetContentViewer(getter_AddRefs(cv)); if (cv) { nsCOMPtr docv(do_QueryInterface(cv)); if (!docv) return NS_OK; nsCOMPtr 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 menubarDOMDoc(GetNamedDOMDoc(nsAutoString("this"))); // XXX "this" is a small kludge for code reused if (menubarDOMDoc) { #ifdef XP_MAC LoadMenus(menubarDOMDoc, mWindow); #else DynamicLoadMenus(menubarDOMDoc, mWindow); #endif } SetSizeFromXUL(); SetTitleFromXUL(); #if 0 nsCOMPtr toolbarDOMDoc(GetNamedDOMDoc(nsAutoString("browser.toolbar"))); nsCOMPtr contentDOMDoc(GetNamedDOMDoc(nsAutoString("browser.webwindow"))); nsCOMPtr contentDoc(do_QueryInterface(contentDOMDoc)); nsCOMPtr statusDoc(do_QueryInterface(statusDOMDoc)); nsCOMPtr 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; } NS_IMETHODIMP nsWebShellWindow::OnStartURLLoad(nsIDocumentLoader* loader, nsIURL* aURL, const char* aContentType, nsIContentViewer* aViewer) { return NS_OK; } NS_IMETHODIMP nsWebShellWindow::OnProgressURLLoad(nsIDocumentLoader* loader, nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax) { return NS_OK; } NS_IMETHODIMP nsWebShellWindow::OnStatusURLLoad(nsIDocumentLoader* loader, nsIURL* aURL, nsString& aMsg) { return NS_OK; } NS_IMETHODIMP nsWebShellWindow::OnEndURLLoad(nsIDocumentLoader* loader, nsIURL* aURL, PRInt32 aStatus) { return NS_OK; } NS_IMETHODIMP nsWebShellWindow::HandleUnknownContentType(nsIDocumentLoader* loader, nsIURL* aURL, const char *aContentType, const char *aCommand ) { return NS_OK; } //---------------------------------------- nsCOMPtr nsWebShellWindow::FindNamedDOMNode(const nsString &aName, nsIDOMNode * aParent, PRInt32 & aCount, PRInt32 aEndCount) { nsCOMPtr node; aParent->GetFirstChild(getter_AddRefs(node)); while (node) { nsString name; node->GetNodeName(name); //printf("FindNamedDOMNode[%s]==[%s] %d == %d\n", aName.ToNewCString(), name.ToNewCString(), aCount+1, aEndCount); //this leaks if (name.Equals(aName)) { aCount++; if (aCount == aEndCount) return node; } PRBool hasChildren; node->HasChildNodes(&hasChildren); if (hasChildren) { nsCOMPtr found(FindNamedDOMNode(aName, node, aCount, aEndCount)); if (found) return found; } nsCOMPtr oldNode = node; oldNode->GetNextSibling(getter_AddRefs(node)); } node = do_QueryInterface(nsnull); return node; } // nsWebShellWindow::FindNamedDOMNode //---------------------------------------- nsCOMPtr nsWebShellWindow::GetParentNodeFromDOMDoc(nsIDOMDocument * aDOMDoc) { nsCOMPtr node; // null if (nsnull == aDOMDoc) { return node; } nsCOMPtr element; aDOMDoc->GetDocumentElement(getter_AddRefs(element)); if (element) return nsCOMPtr(do_QueryInterface(element)); return node; } // nsWebShellWindow::GetParentNodeFromDOMDoc //---------------------------------------- nsCOMPtr nsWebShellWindow::GetNamedDOMDoc(const nsString & aWebShellName) { nsCOMPtr domDoc; // result == nsnull; // first get the toolbar child WebShell nsCOMPtr childWebShell; if (aWebShellName.Equals("this")) { // XXX small kludge for code reused childWebShell = do_QueryInterface(mWebShell); } else { mWebShell->FindChildWithName(aWebShellName.GetUnicode(), *getter_AddRefs(childWebShell)); if (!childWebShell) return domDoc; } nsCOMPtr cv; childWebShell->GetContentViewer(getter_AddRefs(cv)); if (!cv) return domDoc; nsCOMPtr docv(do_QueryInterface(cv)); if (!docv) return domDoc; nsCOMPtr doc; docv->GetDocument(*getter_AddRefs(doc)); if (doc) return nsCOMPtr(do_QueryInterface(doc)); return domDoc; } // nsWebShellWindow::GetNamedDOMDoc //---------------------------------------- PRInt32 nsWebShellWindow::GetDocHeight(nsIDocument * aDoc) { nsIPresShell * presShell = aDoc->GetShellAt(0); if (!presShell) return 0; nsCOMPtr 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()); } } NS_RELEASE(presShell); return 0; } //---------------------------------------- #if 0 NS_IMETHODIMP nsWebShellWindow::OnConnectionsComplete() { #ifdef DEBUG_MENUSDEL printf("OnConnectionsComplete\n"); #endif // register as document listener // this is needed for menus nsCOMPtr cv; mWebShell->GetContentViewer(getter_AddRefs(cv)); if (cv) { nsCOMPtr docv(do_QueryInterface(cv)); if (!docv) return NS_OK; nsCOMPtr 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 menubarDOMDoc(GetNamedDOMDoc(nsAutoString("this"))); // XXX "this" is a small kludge for code reused if (menubarDOMDoc) { #ifdef XP_MAC LoadMenus(menubarDOMDoc, mWindow); #else DynamicLoadMenus(menubarDOMDoc, mWindow); #endif } SetSizeFromXUL(); SetTitleFromXUL(); #if 0 nsCOMPtr toolbarDOMDoc(GetNamedDOMDoc(nsAutoString("browser.toolbar"))); nsCOMPtr contentDOMDoc(GetNamedDOMDoc(nsAutoString("browser.webwindow"))); nsCOMPtr contentDoc(do_QueryInterface(contentDOMDoc)); nsCOMPtr statusDoc(do_QueryInterface(statusDOMDoc)); nsCOMPtr 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 nsWebShellWindow::GetDOMNodeFromWebShell(nsIWebShell *aShell) { nsCOMPtr node; nsCOMPtr cv; aShell->GetContentViewer(getter_AddRefs(cv)); if (cv) { nsCOMPtr docv(do_QueryInterface(cv)); if (docv) { nsCOMPtr doc; docv->GetDocument(*getter_AddRefs(doc)); if (doc) { nsCOMPtr domdoc(do_QueryInterface(doc)); if (domdoc) { nsCOMPtr element; domdoc->GetDocumentElement(getter_AddRefs(element)); if (element) node = do_QueryInterface(element); } } } } return node; } void nsWebShellWindow::ExecuteJavaScriptString(nsString& aJavaScript) { if (aJavaScript.Length() == 0) { return; } // Get nsIScriptContextOwner nsCOMPtr scriptContextOwner ( do_QueryInterface(mWebShell) ); if ( scriptContextOwner ) { const char* url = ""; // Get nsIScriptContext nsCOMPtr 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 } } } /** * Execute window onLoad handler */ void nsWebShellWindow::ExecuteStartupCode() { nsCOMPtr webshellNode = GetDOMNodeFromWebShell(mWebShell); nsCOMPtr webshellElement; if (webshellNode) webshellElement = do_QueryInterface(webshellNode); if (mCallbacks) mCallbacks->ConstructBeforeJavaScript(mWebShell); // Execute the string in the onLoad attribute of the webshellElement. nsString startupCode; if (webshellElement && NS_SUCCEEDED(webshellElement->GetAttribute("onload", startupCode))) ExecuteJavaScriptString(startupCode); if (mCallbacks) mCallbacks->ConstructAfterJavaScript(mWebShell); } /* A somewhat early version of window sizing code. This simply reads attributes from the window tag and blindly sets the size to whatever it finds within. */ void nsWebShellWindow::SetSizeFromXUL() { nsCOMPtr webshellNode = GetDOMNodeFromWebShell(mWebShell); nsIWidget *windowWidget = GetWidget(); nsCOMPtr webshellElement; nsString sizeString; PRInt32 errorCode, specWidth, specHeight, specSize; nsRect currentSize; if (webshellNode) webshellElement = do_QueryInterface(webshellNode); if (!webshellElement || !windowWidget) // it's hopeless return; // first guess: use current size mWindow->GetBounds(currentSize); specWidth = currentSize.width; specHeight = currentSize.height; // read "height" attribute if (NS_SUCCEEDED(webshellElement->GetAttribute("height", sizeString))) { specSize = sizeString.ToInteger(&errorCode); if (NS_SUCCEEDED(errorCode) && specSize > 0) specHeight = specSize; } // read "width" attribute if (NS_SUCCEEDED(webshellElement->GetAttribute("width", sizeString))) { specSize = sizeString.ToInteger(&errorCode); if (NS_SUCCEEDED(errorCode) || specSize > 0) specWidth = specSize; } if (specWidth != currentSize.width || specHeight != currentSize.height) windowWidget->Resize(specWidth, specHeight, PR_TRUE); #if 0 // adjust height to fit contents? if (fitHeight == PR_TRUE) { nsCOMPtr cv; mWebShell->GetContentViewer(getter_AddRefs(cv)); if (cv) { nsCOMPtr docv(do_QueryInterface(cv)); if (docv) { nsCOMPtr doc; docv->GetDocument(*getter_AddRefs(doc)); if (doc) specHeight = GetDocHeight(doc); } } mWindow->GetBounds(currentSize); windowWidget->Resize(currentSize.width, specHeight, PR_TRUE); } #endif } // SetSizeFromXUL void nsWebShellWindow::SetTitleFromXUL() { nsCOMPtr webshellNode = GetDOMNodeFromWebShell(mWebShell); nsIWidget *windowWidget = GetWidget(); nsCOMPtr webshellElement; nsString windowTitle; if (webshellNode) webshellElement = do_QueryInterface(webshellNode); if (webshellElement && windowWidget && NS_SUCCEEDED(webshellElement->GetAttribute("title", windowTitle))) windowWidget->SetTitle(windowTitle); } // SetTitleFromXUL //---------------------------------------------------------------- //-- 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; } NS_IMETHODIMP nsWebShellWindow::ContentStatesChanged(nsIDocument *aDocument, nsIContent* aContent1, nsIContent* aContent2) { return NS_OK; } NS_IMETHODIMP nsWebShellWindow::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent, nsIAtom* aAttribute, PRInt32 aHint) { //printf("AttributeChanged\n"); PRInt32 i; for (i=0;iGetDOMElement(&node); //nsCOMPtr 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 urlObj; // (temporary) rv = NS_NewURL(getter_AddRefs(urlObj), "chrome://navigator/content/"); 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. nsAutoString controllerID("43147b80-8a39-11d2-9938-0080c7cb1081"); // time for this hack to die, or what? rv = Initialize(nsnull, aAppShell, urlObj, controllerID, nsnull, nsnull, aBounds.width, aBounds.height); 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::SizeTo(PRInt32 aWidth, PRInt32 aHeight) { mWindow->Resize(aWidth, aHeight, PR_TRUE); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::GetBounds(nsRect& aResult) { mWindow->GetClientBounds(aResult); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::GetWindowBounds(nsRect& aResult) { mWindow->GetBounds(aResult); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::SetChrome(PRUint32 aNewChromeMask) { // yeah sure. we got your chrome changes. return NS_OK; } NS_IMETHODIMP nsWebShellWindow::GetChrome(PRUint32& aChromeMaskResult) { // Do our best to fake an interesting, rather inapplicable concept from the old world. // We can't tell what sort of chrome features we have until we invent a standard // for XUL chrome elements, and then go looking for them. For now, take a guess... aChromeMaskResult = NS_CHROME_WINDOW_BORDERS_ON | NS_CHROME_WINDOW_CLOSE_ON | NS_CHROME_WINDOW_RESIZE_ON | NS_CHROME_MENU_BAR_ON | NS_CHROME_TOOL_BAR_ON | NS_CHROME_LOCATION_BAR_ON | NS_CHROME_STATUS_BAR_ON | NS_CHROME_PERSONAL_TOOLBAR_ON | NS_CHROME_SCROLLBARS_ON | NS_CHROME_TITLEBAR_ON; return NS_OK; } NS_IMETHODIMP nsWebShellWindow::SetTitle(const PRUnichar* aTitle) { nsIWidget *windowWidget = GetWidget(); if (windowWidget) windowWidget->SetTitle(aTitle); 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; } NS_IMETHODIMP nsWebShellWindow::SetStatus(const PRUnichar* aStatus) { // yup. got it. return NS_OK; } NS_IMETHODIMP nsWebShellWindow::GetStatus(const PRUnichar** aResult) { // didn't store the status string, either. return NS_ERROR_FAILURE; } NS_IMETHODIMP nsWebShellWindow::SetProgress(PRInt32 aProgress, PRInt32 aProgressMax) { // oh yeah. we're on it. return NS_OK; }